Skip to content
Pilotoo
v0.1

Using the library

Connections ship as two packages. @pilotoo/connections-core has no framework: the model, the vault cipher, the OAuth client, the credential resolver, the sharing policy, the provider catalog, the ConnectionStorage port and the built-in GitHub and Gmail providers. @pilotoo/connections-server is the NestJS adapter: the user and admin routes, PostgreSQL storage, maintenance, the two tools and the public tools API. @pilotoo/server re-exports the common names, so a Pilotoo host needs neither directly.

connectionProviders returns the providers to add to your module; connectionControllers are the controllers.

src/app.module.ts
import { Module } from '@nestjs/common';
import { APP_GUARD } from '@nestjs/core';
import { createToolRegistry } from '@pilotoo/agent-runtime';
import { githubProvider, gmailProvider } from '@pilotoo/connections-core';
import { connectionControllers, connectionProviders } from '@pilotoo/connections-server';
import { DatabaseService } from './database.service';
import { IdentityGuard } from './identity.guard';
@Module({
controllers: [...connectionControllers],
providers: [
{ provide: 'ENV', useValue: process.env },
{ provide: 'TOOL_REGISTRY', useFactory: createToolRegistry },
DatabaseService, // exposes `requiredPool`, a pg Pool
{ provide: APP_GUARD, useClass: IdentityGuard },
...connectionProviders(
{ providers: [githubProvider(), gmailProvider()], publicApi: true },
{ env: 'ENV', postgres: DatabaseService, toolRegistry: 'TOOL_REGISTRY' },
),
],
})
export class AppModule {}

The second argument names what the host supplies, as injection tokens:

Port Resolves to
env A NodeJS.ProcessEnv: settings, roles, the vault keys and the maintenance interval are read from it.
postgres An object with requiredPool, a pg Pool. null when the host has no database; then give storage in the options.
toolRegistry The ToolRegistry the opt-in tools register into (from @pilotoo/agent-runtime).

The first argument is ConnectionsHostOptions; see Server integration for tools, storage and http, and Tools API and MCP for publicApi.

Every route reads the caller from request.identity, an Identity of { subject, tenant, roles }. Your guard sets it, and lets through routes marked anonymous, which is only the OAuth callback.

src/identity.guard.ts
import { CanActivate, ExecutionContext, Injectable, UnauthorizedException } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { ANONYMOUS_ROUTE, type IdentifiedRequest } from '@pilotoo/connections-server';
@Injectable()
export class IdentityGuard implements CanActivate {
constructor(private readonly reflector: Reflector) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest<IdentifiedRequest>();
const identity = await resolveCaller(request); // yours
if (identity) request.identity = identity;
else if (!this.reflector.getAllAndOverride<boolean>(ANONYMOUS_ROUTE, [context.getHandler(), context.getClass()])) throw new UnauthorizedException();
return true;
}
}

A route without an identity and without the anonymous mark never runs. The roles in the identity are matched against CONNECTIONS_ROLES and CONNECTIONS_ADMIN_ROLES.

@pilotoo/connections-core alone gives you the services (ConnectionService, ConnectionAdminService, ConnectionCredentialResolver, ProviderCatalog), the AesGcmCredentialCipher and the tool sources. Implement ConnectionStorage for your database and build the services yourself; the Postgres implementation in connections-server is the reference.

import { createCompositeToolSource, createRemoteToolSource, githubProvider } from '@pilotoo/connections-core';