MCP Fusion/Security and governance/Conectores multi-tenant
Conectores multi-tenant
Um conector, muitos tenants, nenhum módulo especial: resolução do tenant por requisição, visibilidade de capacidades filtrada por tags e Presenters baseados em função que mostram a cada tenant o que ele pode ver.
Atender vários clientes com um único conector não é um recurso que você adiciona depois; é uma propriedade de como contexto, visibilidade e percepção são construídos. O MCP Fusion não tem um módulo de tenancy porque as peças que você já usa se compõem em um só padrão. Esta página mostra a receita.
1. Resolva o tenant por requisição
Cada requisição começa com um ctx novo, portanto o tenant é decidido uma vez, antes de qualquer handler:
interface AppContext {
db: PrismaClient;
tenantId: string;
role: 'viewer' | 'admin';
}
registry.attachToServer(server, {
contextFactory: async (extra) => {
const claims = await verify(extra.session?.authToken);
return {
db: pool.forTenant(claims.tenant_id),
tenantId: claims.tenant_id,
role: claims.role,
};
},
});Duas regras tornam isso seguro. A factory retorna um objeto novo por requisição: nenhuma requisição pode observar o contexto de outra. O middleware escreve nesse objeto com proteções contra poluição de protótipo, para que um nome de argumento malicioso não alcance __proto__. Os handlers usam ctx.db ou ctx.tenantId como única porta para os dados, e o id do tenant nunca vem dos argumentos da ferramenta.
2. Limite capacidades por tag
Tenants raramente recebem a mesma superfície. Tags e um filtro decidem o que existe para cada pessoa:
const filterFor = (role: string) =>
role === 'admin'
? { anyTag: ['public', 'admin'] }
: { tags: ['public'], exclude: ['internal'] };
attachToServer(server, { filter: filterFor(ctx.role) });Nesse formato, uma implantação gratuita expõe ferramentas públicas, uma implantação empresarial expõe ferramentas administrativas e a base de código dos handlers é idêntica. O filtro é avaliado onde a lista de ferramentas é construída, sob o próprio contexto da requisição. Consulte Tool exposition.
3. Modele a percepção por função
A visibilidade decide quais ferramentas uma função vê; a percepção decide o que essas ferramentas mostram. O padrão verificado usa duas ferramentas sobre um handler, selecionadas pelo filtro da etapa 2:
const listPeople = async (input, ctx) => ctx.db.people.findMany();
f.query('people.list_public')
.describe('List people in the tenant, without contact details')
.tags('public')
.returns(ViewerPresenter) // schema without email or phone
.handle(listPeople);
f.query('people.list_admin')
.describe('List people in the tenant with full records')
.tags('admin')
.returns(AdminPresenter)
.handle(listPeople); // same handler functionUm agente com função viewer recebe somente people.list_public e nunca vê campos de contato; um agente admin recebe ambas, com o Presenter completo. As regras de campos e a redação ficam em um só lugar por público, e o digest do contrato registra as duas superfícies. Regras contextuais, escritas como (data, ctx) => string[], acrescentam orientação dependente da função. Consulte Models and Presenters.
4. Isole credenciais por tenant
As chaves de fornecedores também não devem ser compartilhadas entre tenants. Declare-as com defineCredentials e leia-as por requisição: no Vinkius Cloud, o runtime injeta os segredos de cada comprador em cada requisição e, localmente, o mesmo accessor lê seu ambiente. Consulte Credentials.
5. Atribua custo e tráfego
Cada chamada pode ser atribuída: passe ctx.tenantId como chave de rate limit para que um tenant não esgote o orçamento de outro e emita o id do tenant em eventos de auditoria e telemetria. No console da Vinkius, o mesmo conector mostra custo e confiabilidade por servidor, documentados em AI spend e Tool reliability.
O padrão em uma tabela
| Concern | Mechanism | Where it lives |
|---|---|---|
| Identity | JWT, API key or OAuth token | contextFactory + auth middleware |
| Data isolation | per-tenant client from the context | contextFactory |
| Capability visibility | tags + filter | tool list construction |
| Field isolation | role-based Presenters | Presenter per audience |
| Secret isolation | BYOC credentials | runtime injection |
| Fair use | rate-limit key from ctx | rate limiter middleware |
| Proof | contract digest + audit events | lockfile and audit sink |
Não existe um switch de runtime para esquecer nem um cache entre tenants para configurar incorretamente, porque nada é compartilhado a menos que você o compartilhe explicitamente. Essa é a diferença entre um conector multi-tenant e um conector single-tenant com uma coluna de tenant.
Próximos passos
- Authentication: de onde vem a identidade
- Middleware and context: mecânicas de derivação e isolamento
- Security pipeline: as camadas atravessadas por cada requisição
