@mcpolyglot/core 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/__tests__/pipeline.test.d.ts +2 -0
- package/dist/__tests__/pipeline.test.d.ts.map +1 -0
- package/dist/__tests__/pipeline.test.js +178 -0
- package/dist/__tests__/pipeline.test.js.map +1 -0
- package/dist/__tests__/streamable-http.test.js +43 -2
- package/dist/__tests__/streamable-http.test.js.map +1 -1
- package/dist/connector.d.ts +0 -14
- package/dist/connector.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +42 -8
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +80 -33
- package/dist/server.js.map +1 -1
- package/dist/tool.d.ts +2 -3
- package/dist/tool.d.ts.map +1 -1
- package/dist/tool.js.map +1 -1
- package/dist/transport.d.ts +5 -2
- package/dist/transport.d.ts.map +1 -1
- package/dist/transports/stdio.d.ts +1 -1
- package/dist/transports/stdio.d.ts.map +1 -1
- package/dist/transports/stdio.js +2 -2
- package/dist/transports/stdio.js.map +1 -1
- package/dist/transports/streamable-http.d.ts +28 -4
- package/dist/transports/streamable-http.d.ts.map +1 -1
- package/dist/transports/streamable-http.js +59 -13
- package/dist/transports/streamable-http.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/pipeline.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
4
|
+
import { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js';
|
|
5
|
+
import { McpolyglotServer } from '../server.js';
|
|
6
|
+
import { McpolyglotError } from '../errors.js';
|
|
7
|
+
const SECRET_ARG = 'super-secret-arg-value';
|
|
8
|
+
let handlerCalls = 0;
|
|
9
|
+
function fakeConnector() {
|
|
10
|
+
return {
|
|
11
|
+
id: 'fake',
|
|
12
|
+
kind: 'sql',
|
|
13
|
+
init: async () => { },
|
|
14
|
+
close: async () => { },
|
|
15
|
+
health: async () => ({ ok: true, latencyMs: 0 }),
|
|
16
|
+
introspect: async () => ({ kind: 'sql', tables: [] }),
|
|
17
|
+
listPrimitiveTools: () => [
|
|
18
|
+
{
|
|
19
|
+
name: 'fake.ok',
|
|
20
|
+
description: 'ok',
|
|
21
|
+
inputSchema: z.object({ q: z.string() }),
|
|
22
|
+
scopes: [],
|
|
23
|
+
readOnly: true,
|
|
24
|
+
handler: async () => ({
|
|
25
|
+
content: [{ type: 'json', data: [{ secret_row: 'row-data' }] }],
|
|
26
|
+
metadata: { rows: 1 },
|
|
27
|
+
}),
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
name: 'fake.denied',
|
|
31
|
+
description: 'denied',
|
|
32
|
+
inputSchema: z.object({ q: z.string() }),
|
|
33
|
+
scopes: [],
|
|
34
|
+
readOnly: true,
|
|
35
|
+
handler: async () => {
|
|
36
|
+
throw new McpolyglotError('forbidden.policy', 'Table "x" is not accessible.');
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: 'fake.scoped',
|
|
41
|
+
description: 'needs a scope nobody has',
|
|
42
|
+
inputSchema: z.object({}),
|
|
43
|
+
scopes: ['tables:write'],
|
|
44
|
+
readOnly: false,
|
|
45
|
+
handler: async () => {
|
|
46
|
+
handlerCalls += 1;
|
|
47
|
+
return { content: [] };
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: 'fake.slow',
|
|
52
|
+
description: 'ignores the abort signal and never returns in time',
|
|
53
|
+
inputSchema: z.object({}),
|
|
54
|
+
scopes: [],
|
|
55
|
+
readOnly: true,
|
|
56
|
+
handler: () => new Promise(() => { }),
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: 'fake.broken',
|
|
60
|
+
description: 'broken',
|
|
61
|
+
inputSchema: z.object({ q: z.string() }),
|
|
62
|
+
scopes: [],
|
|
63
|
+
readOnly: true,
|
|
64
|
+
handler: async () => {
|
|
65
|
+
throw new Error('boom');
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
async function boot(opts = {}) {
|
|
72
|
+
const entries = [];
|
|
73
|
+
const rate = { taken: 0, released: 0 };
|
|
74
|
+
const passthrough = (_, r) => r;
|
|
75
|
+
const server = new McpolyglotServer({
|
|
76
|
+
connectors: [fakeConnector()],
|
|
77
|
+
security: {
|
|
78
|
+
hooks: {
|
|
79
|
+
checkScopes: (_name, required, granted) => {
|
|
80
|
+
const missing = required.filter((s) => !granted.has(s));
|
|
81
|
+
if (missing.length)
|
|
82
|
+
throw new McpolyglotError('forbidden.scope', `missing ${missing}`);
|
|
83
|
+
},
|
|
84
|
+
checkRateLimit: async () => {
|
|
85
|
+
rate.taken += 1;
|
|
86
|
+
return () => {
|
|
87
|
+
rate.released += 1;
|
|
88
|
+
};
|
|
89
|
+
},
|
|
90
|
+
redact: (_t, result) => ({ result, redactionsApplied: 0 }),
|
|
91
|
+
enforceSize: passthrough,
|
|
92
|
+
wrapUntrusted: (r) => r,
|
|
93
|
+
audit: async (e) => {
|
|
94
|
+
entries.push(e);
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
defaultLimits: { rowCap: 10, timeoutMs: opts.timeoutMs ?? 5_000, maxBytes: 65_536 },
|
|
98
|
+
defaultScopes: [],
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
const [clientSide, serverSide] = InMemoryTransport.createLinkedPair();
|
|
102
|
+
const transport = {
|
|
103
|
+
kind: 'stdio',
|
|
104
|
+
start: (create) => create().connect(serverSide),
|
|
105
|
+
stop: async () => { },
|
|
106
|
+
};
|
|
107
|
+
await server.start(transport);
|
|
108
|
+
const client = new Client({ name: 'test-agent', version: '1.0.0' });
|
|
109
|
+
await client.connect(clientSide);
|
|
110
|
+
return { client, entries, server, rate };
|
|
111
|
+
}
|
|
112
|
+
describe('audit entries', () => {
|
|
113
|
+
it('records allow / deny / error with agent id, reason, rows, latency — never raw args or rows', async () => {
|
|
114
|
+
const { client, entries, server } = await boot();
|
|
115
|
+
await client.callTool({ name: 'fake.ok', arguments: { q: SECRET_ARG } });
|
|
116
|
+
await client.callTool({ name: 'fake.denied', arguments: { q: SECRET_ARG } });
|
|
117
|
+
await client.callTool({ name: 'fake.broken', arguments: { q: SECRET_ARG } }).catch(() => { });
|
|
118
|
+
expect(entries.map((e) => [e.tool, e.decision])).toEqual([
|
|
119
|
+
['fake.ok', 'allow'],
|
|
120
|
+
['fake.denied', 'deny'],
|
|
121
|
+
['fake.broken', 'error'],
|
|
122
|
+
]);
|
|
123
|
+
for (const e of entries) {
|
|
124
|
+
expect(e.agentId).toBe('test-agent');
|
|
125
|
+
expect(e.argsHash).toMatch(/^[0-9a-f]{16}$/);
|
|
126
|
+
expect(typeof e.durationMs).toBe('number');
|
|
127
|
+
expect(Date.parse(e.ts)).not.toBeNaN();
|
|
128
|
+
}
|
|
129
|
+
expect(entries[0].rows).toBe(1);
|
|
130
|
+
expect(entries[0].reason).toBeUndefined();
|
|
131
|
+
expect(entries[1].reason).toContain('not accessible');
|
|
132
|
+
expect(entries[2].reason).toBe('boom');
|
|
133
|
+
const serialized = JSON.stringify(entries);
|
|
134
|
+
expect(serialized).not.toContain(SECRET_ARG);
|
|
135
|
+
expect(serialized).not.toContain('row-data');
|
|
136
|
+
await server.stop();
|
|
137
|
+
});
|
|
138
|
+
it('same args → same hash; different args → different hash', async () => {
|
|
139
|
+
const { client, entries, server } = await boot();
|
|
140
|
+
await client.callTool({ name: 'fake.ok', arguments: { q: 'a' } });
|
|
141
|
+
await client.callTool({ name: 'fake.ok', arguments: { q: 'a' } });
|
|
142
|
+
await client.callTool({ name: 'fake.ok', arguments: { q: 'b' } });
|
|
143
|
+
expect(entries[0].argsHash).toBe(entries[1].argsHash);
|
|
144
|
+
expect(entries[0].argsHash).not.toBe(entries[2].argsHash);
|
|
145
|
+
await server.stop();
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
describe('pipeline guarantees', () => {
|
|
149
|
+
it('scope check rejects before the handler runs', async () => {
|
|
150
|
+
const { client, entries, server } = await boot();
|
|
151
|
+
handlerCalls = 0;
|
|
152
|
+
const r = await client.callTool({ name: 'fake.scoped', arguments: {} });
|
|
153
|
+
expect(r.isError).toBe(true);
|
|
154
|
+
expect(handlerCalls).toBe(0);
|
|
155
|
+
expect(entries[0]).toMatchObject({ decision: 'deny', error: { code: 'forbidden.scope' } });
|
|
156
|
+
await server.stop();
|
|
157
|
+
});
|
|
158
|
+
it('a handler that never returns is cut off at the timeout', async () => {
|
|
159
|
+
const { client, entries, server } = await boot({ timeoutMs: 100 });
|
|
160
|
+
const t0 = Date.now();
|
|
161
|
+
const r = await client.callTool({ name: 'fake.slow', arguments: {} });
|
|
162
|
+
expect(Date.now() - t0).toBeLessThan(2_000);
|
|
163
|
+
expect(r.isError).toBe(true);
|
|
164
|
+
expect(entries[0]).toMatchObject({ decision: 'deny', error: { code: 'timeout' } });
|
|
165
|
+
await server.stop();
|
|
166
|
+
});
|
|
167
|
+
it('releases the rate-limit slot on success, deny, timeout and error', async () => {
|
|
168
|
+
const { client, server, rate } = await boot({ timeoutMs: 100 });
|
|
169
|
+
for (const name of ['fake.ok', 'fake.denied', 'fake.slow', 'fake.broken']) {
|
|
170
|
+
await client
|
|
171
|
+
.callTool({ name, arguments: name === 'fake.slow' ? {} : { q: 'x' } })
|
|
172
|
+
.catch(() => { });
|
|
173
|
+
}
|
|
174
|
+
expect(rate).toEqual({ taken: 4, released: 4 });
|
|
175
|
+
await server.stop();
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
//# sourceMappingURL=pipeline.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.test.js","sourceRoot":"","sources":["../../src/__tests__/pipeline.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAmB,MAAM,cAAc,CAAC;AAGjE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,MAAM,UAAU,GAAG,wBAAwB,CAAC;AAE5C,IAAI,YAAY,GAAG,CAAC,CAAC;AAErB,SAAS,aAAa;IACpB,OAAO;QACL,EAAE,EAAE,MAAM;QACV,IAAI,EAAE,KAAK;QACX,IAAI,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;QACpB,KAAK,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;QACrB,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;QAChD,UAAU,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QACrD,kBAAkB,EAAE,GAAG,EAAE,CAAC;YACxB;gBACE,IAAI,EAAE,SAAS;gBACf,WAAW,EAAE,IAAI;gBACjB,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;gBACxC,MAAM,EAAE,EAAE;gBACV,QAAQ,EAAE,IAAI;gBACd,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;oBACpB,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC;oBAC/D,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE;iBACtB,CAAC;aACH;YACD;gBACE,IAAI,EAAE,aAAa;gBACnB,WAAW,EAAE,QAAQ;gBACrB,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;gBACxC,MAAM,EAAE,EAAE;gBACV,QAAQ,EAAE,IAAI;gBACd,OAAO,EAAE,KAAK,IAAI,EAAE;oBAClB,MAAM,IAAI,eAAe,CAAC,kBAAkB,EAAE,8BAA8B,CAAC,CAAC;gBAChF,CAAC;aACF;YACD;gBACE,IAAI,EAAE,aAAa;gBACnB,WAAW,EAAE,0BAA0B;gBACvC,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;gBACzB,MAAM,EAAE,CAAC,cAAc,CAAC;gBACxB,QAAQ,EAAE,KAAK;gBACf,OAAO,EAAE,KAAK,IAAI,EAAE;oBAClB,YAAY,IAAI,CAAC,CAAC;oBAClB,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;gBACzB,CAAC;aACF;YACD;gBACE,IAAI,EAAE,WAAW;gBACjB,WAAW,EAAE,oDAAoD;gBACjE,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;gBACzB,MAAM,EAAE,EAAE;gBACV,QAAQ,EAAE,IAAI;gBACd,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,OAAO,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC;aACrC;YACD;gBACE,IAAI,EAAE,aAAa;gBACnB,WAAW,EAAE,QAAQ;gBACrB,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;gBACxC,MAAM,EAAE,EAAE;gBACV,QAAQ,EAAE,IAAI;gBACd,OAAO,EAAE,KAAK,IAAI,EAAE;oBAClB,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC;gBAC1B,CAAC;aACF;SACF;KACsB,CAAC;AAC5B,CAAC;AAED,KAAK,UAAU,IAAI,CAAC,OAA+B,EAAE;IACnD,MAAM,OAAO,GAAiB,EAAE,CAAC;IACjC,MAAM,IAAI,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IACvC,MAAM,WAAW,GAAG,CAAC,CAAS,EAAE,CAAQ,EAAE,EAAE,CAAC,CAAC,CAAC;IAC/C,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC;QAClC,UAAU,EAAE,CAAC,aAAa,EAAE,CAAC;QAC7B,QAAQ,EAAE;YACR,KAAK,EAAE;gBACL,WAAW,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE;oBACxC,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;oBACxD,IAAI,OAAO,CAAC,MAAM;wBAAE,MAAM,IAAI,eAAe,CAAC,iBAAiB,EAAE,WAAW,OAAO,EAAE,CAAC,CAAC;gBACzF,CAAC;gBACD,cAAc,EAAE,KAAK,IAAI,EAAE;oBACzB,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC;oBAChB,OAAO,GAAG,EAAE;wBACV,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC;oBACrB,CAAC,CAAC;gBACJ,CAAC;gBACD,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC,EAAE,CAAC;gBAC1D,WAAW,EAAE,WAAW;gBACxB,aAAa,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACvB,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;oBACjB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAClB,CAAC;aACF;YACD,aAAa,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE;YACnF,aAAa,EAAE,EAAE;SAClB;KACF,CAAC,CAAC;IACH,MAAM,CAAC,UAAU,EAAE,UAAU,CAAC,GAAG,iBAAiB,CAAC,gBAAgB,EAAE,CAAC;IACtE,MAAM,SAAS,GAAc;QAC3B,IAAI,EAAE,OAAO;QACb,KAAK,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC;QAC/C,IAAI,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;KACrB,CAAC;IACF,MAAM,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAC9B,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IACpE,MAAM,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACjC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AAC3C,CAAC;AAED,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,EAAE,CAAC,4FAA4F,EAAE,KAAK,IAAI,EAAE;QAC1G,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,EAAE,CAAC;QACjD,MAAM,MAAM,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC;QACzE,MAAM,MAAM,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,SAAS,EAAE,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC;QAC7E,MAAM,MAAM,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,SAAS,EAAE,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAE7F,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;YACvD,CAAC,SAAS,EAAE,OAAO,CAAC;YACpB,CAAC,aAAa,EAAE,MAAM,CAAC;YACvB,CAAC,aAAa,EAAE,OAAO,CAAC;SACzB,CAAC,CAAC;QACH,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACrC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;YAC7C,MAAM,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC3C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QACzC,CAAC;QACD,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,MAAM,CAAC,CAAC,aAAa,EAAE,CAAC;QAC3C,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;QACvD,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAExC,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAC3C,MAAM,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAC7C,MAAM,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAC7C,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;IACtB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;QACtE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,EAAE,CAAC;QACjD,MAAM,MAAM,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;QAClE,MAAM,MAAM,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;QAClE,MAAM,MAAM,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;QAClE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,QAAQ,CAAC,CAAC;QACxD,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,QAAQ,CAAC,CAAC;QAC5D,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;IACtB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;IACnC,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;QAC3D,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,EAAE,CAAC;QACjD,YAAY,GAAG,CAAC,CAAC;QACjB,MAAM,CAAC,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC;QACxE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7B,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC7B,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,iBAAiB,EAAE,EAAE,CAAC,CAAC;QAC3F,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;IACtB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;QACtE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;QACnE,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACtB,MAAM,CAAC,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC;QACtE,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QAC5C,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7B,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;QACnF,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;IACtB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;QAChF,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;QAChE,KAAK,MAAM,IAAI,IAAI,CAAC,SAAS,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,CAAC,EAAE,CAAC;YAC1E,MAAM,MAAM;iBACT,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC;iBACrE,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACrB,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;QAChD,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;IACtB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { afterEach, describe, expect, it } from 'vitest';
|
|
2
2
|
import { Server as McpServer } from '@modelcontextprotocol/sdk/server/index.js';
|
|
3
|
-
import { StreamableHttpTransport } from '../transports/streamable-http.js';
|
|
3
|
+
import { hashToken, matchAgent, StreamableHttpTransport } from '../transports/streamable-http.js';
|
|
4
4
|
// Silence the JSON banner the transport emits to stderr during tests.
|
|
5
5
|
const silentLogger = { info: () => { }, warn: () => { } };
|
|
6
6
|
async function fetchStatus(url, init) {
|
|
@@ -25,7 +25,7 @@ describe('StreamableHttpTransport', () => {
|
|
|
25
25
|
...opts,
|
|
26
26
|
logger: silentLogger,
|
|
27
27
|
});
|
|
28
|
-
await transport.start(mcpServer);
|
|
28
|
+
await transport.start(() => mcpServer);
|
|
29
29
|
// We bind on port 0 so the OS picks; recover the real port from the
|
|
30
30
|
// listening socket. Field access is intentional — the public class
|
|
31
31
|
// doesn't expose the address since the CLI already knows it.
|
|
@@ -60,5 +60,46 @@ describe('StreamableHttpTransport', () => {
|
|
|
60
60
|
expect(typeof transport.bearerToken).toBe('string');
|
|
61
61
|
expect(transport.bearerToken.length).toBeGreaterThan(16);
|
|
62
62
|
});
|
|
63
|
+
it('agents mode: known token passes, revoked and unknown tokens get 401', async () => {
|
|
64
|
+
await boot({
|
|
65
|
+
host: '127.0.0.1',
|
|
66
|
+
port: 0,
|
|
67
|
+
auth: {
|
|
68
|
+
kind: 'agents',
|
|
69
|
+
agents: [
|
|
70
|
+
{
|
|
71
|
+
id: 'a',
|
|
72
|
+
tokens: [{ hash: hashToken('old'), revoked: true }, { hash: hashToken('new') }],
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
expect(transport.bearerToken).toBeUndefined();
|
|
78
|
+
const call = (token) => fetchStatus(`${baseUrl}/mcp`, {
|
|
79
|
+
method: 'POST',
|
|
80
|
+
headers: { authorization: `Bearer ${token}` },
|
|
81
|
+
});
|
|
82
|
+
expect((await call('old')).status).toBe(401);
|
|
83
|
+
expect((await call('nope')).status).toBe(401);
|
|
84
|
+
// Past auth; the SDK then rejects the empty body, which is not a 401.
|
|
85
|
+
expect((await call('new')).status).not.toBe(401);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
describe('agent token hashing', () => {
|
|
89
|
+
it('hashToken is sha256 hex', () => {
|
|
90
|
+
// sha256("abc"), FIPS 180-2 test vector.
|
|
91
|
+
expect(hashToken('abc')).toBe('ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad');
|
|
92
|
+
});
|
|
93
|
+
it('matchAgent finds the owner and nothing for unknown or malformed hashes', () => {
|
|
94
|
+
const hashes = [
|
|
95
|
+
{ agentId: 'bad', hash: Buffer.from('abcd', 'hex') },
|
|
96
|
+
{ agentId: 'a', hash: Buffer.from(hashToken('ta'), 'hex') },
|
|
97
|
+
{ agentId: 'b', hash: Buffer.from(hashToken('tb'), 'hex') },
|
|
98
|
+
];
|
|
99
|
+
expect(matchAgent(hashes, 'ta')).toBe('a');
|
|
100
|
+
expect(matchAgent(hashes, 'tb')).toBe('b');
|
|
101
|
+
expect(matchAgent(hashes, 'tc')).toBeUndefined();
|
|
102
|
+
expect(matchAgent([], 'ta')).toBeUndefined();
|
|
103
|
+
});
|
|
63
104
|
});
|
|
64
105
|
//# sourceMappingURL=streamable-http.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"streamable-http.test.js","sourceRoot":"","sources":["../../src/__tests__/streamable-http.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACzD,OAAO,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,2CAA2C,CAAC;AAChF,OAAO,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"streamable-http.test.js","sourceRoot":"","sources":["../../src/__tests__/streamable-http.test.ts"],"names":[],"mappings":"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"}
|
package/dist/connector.d.ts
CHANGED
|
@@ -69,17 +69,6 @@ export type SchemaSnapshot = {
|
|
|
69
69
|
kind: 'openapi';
|
|
70
70
|
operations: OperationSchema[];
|
|
71
71
|
};
|
|
72
|
-
/**
|
|
73
|
-
* Per-source configuration for opt-in per-entity tools (e.g., `users.find_by_email`).
|
|
74
|
-
* When `enabled` is `false`, only primitive tools (`list_tables`, `query`, …) are exposed.
|
|
75
|
-
*/
|
|
76
|
-
export interface PerEntityConfig {
|
|
77
|
-
enabled: boolean;
|
|
78
|
-
/** Glob-like patterns of entities (tables/collections) to include. Wins over `exclude` if both are set. */
|
|
79
|
-
include?: string[];
|
|
80
|
-
/** Glob-like patterns of entities to exclude. */
|
|
81
|
-
exclude?: string[];
|
|
82
|
-
}
|
|
83
72
|
/** Runtime context handed to a connector's `init()`. */
|
|
84
73
|
export interface ConnectorInitCtx {
|
|
85
74
|
logger: {
|
|
@@ -108,7 +97,6 @@ export interface ConnectorInitCtx {
|
|
|
108
97
|
* async health() { return { ok: true, latencyMs: 0 }; }
|
|
109
98
|
* async introspect() { return { kind: 'sql', tables: [] }; }
|
|
110
99
|
* listPrimitiveTools() { return []; } // ToolDefinition[]
|
|
111
|
-
* generatePerEntityTools() { return []; }
|
|
112
100
|
* }
|
|
113
101
|
* ```
|
|
114
102
|
*/
|
|
@@ -124,8 +112,6 @@ export interface Connector {
|
|
|
124
112
|
introspect(): Promise<SchemaSnapshot>;
|
|
125
113
|
/** Tools always exposed for this source (e.g., `list_tables`, `query`). */
|
|
126
114
|
listPrimitiveTools(): ToolDefinition[];
|
|
127
|
-
/** Per-entity tools to expose when `cfg.enabled` is `true` (e.g., `users.find_by_email`). */
|
|
128
|
-
generatePerEntityTools(cfg: PerEntityConfig): ToolDefinition[];
|
|
129
115
|
/** Lightweight ping. Used by `mcpolyglot doctor` and HTTP `/healthz`. */
|
|
130
116
|
health(): Promise<{
|
|
131
117
|
ok: boolean;
|
package/dist/connector.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connector.d.ts","sourceRoot":"","sources":["../src/connector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEhD,qEAAqE;AACrE,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,OAAO,GAAG,SAAS,CAAC;AAExD,8CAA8C;AAC9C,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAChD;AAED,uFAAuF;AACvF,MAAM,WAAW,WAAW;IAC1B,mGAAmG;IACnG,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,uEAAuE;IACvE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,aAAa,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAC3E,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,wEAAwE;AACxE,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,KAAK,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,EAAE,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;QAChC,QAAQ,EAAE,OAAO,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC,CAAC;IACH,WAAW,CAAC,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3D;AAED;;;GAGG;AACH,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,WAAW,EAAE,CAAA;CAAE,GACtC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,gBAAgB,EAAE,CAAA;CAAE,GAClD;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,UAAU,EAAE,eAAe,EAAE,CAAA;CAAE,CAAC;AAEvD
|
|
1
|
+
{"version":3,"file":"connector.d.ts","sourceRoot":"","sources":["../src/connector.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export type { Connector, ConnectorInitCtx, ConnectorKind,
|
|
1
|
+
export type { Connector, ConnectorInitCtx, ConnectorKind, SchemaSnapshot, TableSchema, CollectionSchema, OperationSchema, ColumnSchema, } from './connector.js';
|
|
2
2
|
export type { ToolDefinition, ToolHandler, ToolExecCtx, ToolExecLimits, ToolResult, ContentBlock, Scope, } from './tool.js';
|
|
3
3
|
export { ALL_SCOPES, DEFAULT_SCOPES } from './tool.js';
|
|
4
|
-
export { McpolyglotServer, type McpolyglotServerOptions, type SecurityServices, type SecurityHooks, } from './server.js';
|
|
4
|
+
export { McpolyglotServer, type McpolyglotServerOptions, type AgentGrant, type SecurityServices, type SecurityHooks, } from './server.js';
|
|
5
5
|
export type { Transport } from './transport.js';
|
|
6
6
|
export { McpolyglotError, ScopeError, RateLimitError, TimeoutError, ConfigError, } from './errors.js';
|
|
7
7
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,SAAS,EACT,gBAAgB,EAChB,aAAa,EACb,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,SAAS,EACT,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,YAAY,GACb,MAAM,gBAAgB,CAAC;AAExB,YAAY,EACV,cAAc,EACd,WAAW,EACX,WAAW,EACX,cAAc,EACd,UAAU,EACV,YAAY,EACZ,KAAK,GACN,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEvD,OAAO,EACL,gBAAgB,EAChB,KAAK,uBAAuB,EAC5B,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,KAAK,aAAa,GACnB,MAAM,aAAa,CAAC;AAErB,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,OAAO,EACL,eAAe,EACf,UAAU,EACV,cAAc,EACd,YAAY,EACZ,WAAW,GACZ,MAAM,aAAa,CAAC"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEvD,OAAO,EACL,gBAAgB,GAKjB,MAAM,aAAa,CAAC;AAIrB,OAAO,EACL,eAAe,EACf,UAAU,EACV,cAAc,EACd,YAAY,EACZ,WAAW,GACZ,MAAM,aAAa,CAAC"}
|
package/dist/server.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Connector
|
|
1
|
+
import type { Connector } from './connector.js';
|
|
2
2
|
import type { Transport } from './transport.js';
|
|
3
3
|
import { type Scope, type ToolExecLimits, type ToolResult } from './tool.js';
|
|
4
4
|
/**
|
|
@@ -11,8 +11,11 @@ import { type Scope, type ToolExecLimits, type ToolResult } from './tool.js';
|
|
|
11
11
|
export interface SecurityHooks {
|
|
12
12
|
/** Phase 1 — reject if granted scopes don't cover the tool's required scopes. */
|
|
13
13
|
checkScopes(toolName: string, required: readonly Scope[], granted: ReadonlySet<Scope>): void;
|
|
14
|
-
/**
|
|
15
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Phase 2 — token-bucket + concurrency gate. Throws `RateLimitError` on violation. May
|
|
16
|
+
* return a release function; the server calls it when the call finishes.
|
|
17
|
+
*/
|
|
18
|
+
checkRateLimit(toolName: string, sessionId: string): Promise<void | (() => void)>;
|
|
16
19
|
/** Phase 5 — strip secrets, drop denied columns. Returns the new result and the redaction count. */
|
|
17
20
|
redact(toolName: string, result: ToolResult): {
|
|
18
21
|
result: ToolResult;
|
|
@@ -39,7 +42,16 @@ export interface AuditEntry {
|
|
|
39
42
|
/** ISO-8601 UTC timestamp. */
|
|
40
43
|
ts: string;
|
|
41
44
|
sessionId: string;
|
|
45
|
+
/**
|
|
46
|
+
* The agent authenticated by its HTTP token when `agents` is configured. Otherwise
|
|
47
|
+
* client-asserted: the `x-mcpolyglot-agent` header (HTTP), else MCP `clientInfo.name`.
|
|
48
|
+
*/
|
|
49
|
+
agentId?: string;
|
|
42
50
|
tool: string;
|
|
51
|
+
/** `deny` = rejected by policy/scope/rate limit/timeout; `error` = anything else that failed. */
|
|
52
|
+
decision: 'allow' | 'deny' | 'error';
|
|
53
|
+
/** Why the call was denied or failed. */
|
|
54
|
+
reason?: string;
|
|
43
55
|
/** First 16 chars of `sha256(JSON.stringify(args))`. Enough for forensics, not for reconstruction. */
|
|
44
56
|
argsHash: string;
|
|
45
57
|
scopes: Scope[];
|
|
@@ -57,11 +69,15 @@ export interface McpolyglotServerOptions {
|
|
|
57
69
|
name?: string;
|
|
58
70
|
version?: string;
|
|
59
71
|
connectors: Connector[];
|
|
60
|
-
/** Per-source per-entity configuration. Keyed by `connector.id`. */
|
|
61
|
-
perEntity?: Record<string, PerEntityConfig>;
|
|
62
72
|
/** Scopes granted to the calling session. Defaults to `DEFAULT_SCOPES` (read-only). */
|
|
63
73
|
scopes?: readonly Scope[];
|
|
64
74
|
security: SecurityServices;
|
|
75
|
+
/**
|
|
76
|
+
* Per-agent grants. A request whose transport authenticated one of these ids (via
|
|
77
|
+
* `authInfo.clientId`) sees only that agent's connectors and scopes. Requests without an
|
|
78
|
+
* authenticated agent (stdio, plain bearer) use `connectors` + `scopes` as before.
|
|
79
|
+
*/
|
|
80
|
+
agents?: AgentGrant[];
|
|
65
81
|
logger?: {
|
|
66
82
|
debug: (msg: string, fields?: Record<string, unknown>) => void;
|
|
67
83
|
info: (msg: string, fields?: Record<string, unknown>) => void;
|
|
@@ -69,6 +85,13 @@ export interface McpolyglotServerOptions {
|
|
|
69
85
|
error: (msg: string, fields?: Record<string, unknown>) => void;
|
|
70
86
|
};
|
|
71
87
|
}
|
|
88
|
+
/** What one authenticated agent may use. */
|
|
89
|
+
export interface AgentGrant {
|
|
90
|
+
id: string;
|
|
91
|
+
scopes: readonly Scope[];
|
|
92
|
+
/** Connectors this agent sees; may be per-agent instances (e.g. with their own policy). */
|
|
93
|
+
connectors: Connector[];
|
|
94
|
+
}
|
|
72
95
|
/**
|
|
73
96
|
* MCP server that wires connectors + security hooks + a transport.
|
|
74
97
|
*
|
|
@@ -94,19 +117,30 @@ export interface McpolyglotServerOptions {
|
|
|
94
117
|
* ```
|
|
95
118
|
*/
|
|
96
119
|
export declare class McpolyglotServer {
|
|
97
|
-
private readonly
|
|
120
|
+
private readonly info;
|
|
98
121
|
private readonly tools;
|
|
99
122
|
private readonly connectors;
|
|
100
|
-
private readonly perEntity;
|
|
101
123
|
private readonly scopes;
|
|
124
|
+
private readonly agents;
|
|
102
125
|
private readonly security;
|
|
103
126
|
private readonly sessionId;
|
|
104
127
|
private readonly logger;
|
|
105
128
|
private transport?;
|
|
106
129
|
constructor(opts: McpolyglotServerOptions);
|
|
130
|
+
/**
|
|
131
|
+
* A fresh MCP protocol server bound to this instance's tools and pipeline. Stdio makes one;
|
|
132
|
+
* the stateless HTTP transport makes one per request (the SDK forbids reusing either).
|
|
133
|
+
*/
|
|
134
|
+
private createMcpServer;
|
|
107
135
|
start(transport: Transport): Promise<void>;
|
|
108
136
|
stop(): Promise<void>;
|
|
109
|
-
private
|
|
137
|
+
private allConnectors;
|
|
138
|
+
private toolsOf;
|
|
139
|
+
/**
|
|
140
|
+
* Who is calling. Only `authInfo` set by our HTTP transport identifies an agent; headers
|
|
141
|
+
* and clientInfo are client-asserted and only used as an audit label when it's absent.
|
|
142
|
+
*/
|
|
143
|
+
private caller;
|
|
110
144
|
/**
|
|
111
145
|
* Fixed pipeline: scope check → rate limit → timeout → handler →
|
|
112
146
|
* redaction → size cap → untrusted-wrap → audit log → response.
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|