@plurnk/plurnk-mcp 1.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/.env.defaults +19 -0
- package/LICENSE +21 -0
- package/README.md +69 -0
- package/SPEC.md +48 -0
- package/dist/McpExecutor.d.ts +16 -0
- package/dist/McpExecutor.d.ts.map +1 -0
- package/dist/McpExecutor.js +127 -0
- package/dist/McpExecutor.js.map +1 -0
- package/dist/McpResources.d.ts +10 -0
- package/dist/McpResources.d.ts.map +1 -0
- package/dist/McpResources.js +153 -0
- package/dist/McpResources.js.map +1 -0
- package/dist/Module.d.ts +29 -0
- package/dist/Module.d.ts.map +1 -0
- package/dist/Module.js +55 -0
- package/dist/Module.js.map +1 -0
- package/dist/client.d.ts +28 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +153 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +18 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +134 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/package.json +66 -0
package/.env.defaults
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# --- @plurnk/plurnk-mcp : current MCP host module ---
|
|
2
|
+
|
|
3
|
+
# Bound only connection and protocol discovery. Individual MCP operations use
|
|
4
|
+
# the request timeout below and remain cancellable through their Plurnk run.
|
|
5
|
+
PLURNK_MCP_CONNECT_TIMEOUT=30000
|
|
6
|
+
PLURNK_MCP_REQUEST_TIMEOUT=86400000
|
|
7
|
+
|
|
8
|
+
# Each configured server becomes EXEC[<server>] and <server>://.
|
|
9
|
+
#
|
|
10
|
+
# Streamable HTTP:
|
|
11
|
+
# PLURNK_MCP_github=https://example.test/mcp
|
|
12
|
+
# PLURNK_MCP_github_HEADERS={"Authorization":"Bearer ${GITHUB_TOKEN}"}
|
|
13
|
+
#
|
|
14
|
+
# stdio: the target is one executable. Arguments are a JSON array so Plurnk
|
|
15
|
+
# does not invent or interpret a shell command language.
|
|
16
|
+
# PLURNK_MCP_atlas=node
|
|
17
|
+
# PLURNK_MCP_atlas_ARGS=["/absolute/path/to/atlas-server.mjs"]
|
|
18
|
+
# PLURNK_MCP_atlas_CWD=/absolute/working/directory
|
|
19
|
+
# PLURNK_MCP_atlas_ENV={"TOKEN":"${ATLAS_TOKEN}"}
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 PossumTech Laboratories
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# @plurnk/plurnk-mcp
|
|
2
|
+
|
|
3
|
+
The current [Model Context Protocol](https://modelcontextprotocol.io/) host
|
|
4
|
+
module for [Plurnk](https://github.com/plurnk/plurnk-service).
|
|
5
|
+
|
|
6
|
+
Each configured MCP server becomes a model-facing executor and resource
|
|
7
|
+
authority:
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
<<READ(github:///):READ
|
|
11
|
+
<<EXEC[github](create_issue):{"title":"Bug"}:EXEC
|
|
12
|
+
<<FIND(github:///resources/**)::FIND
|
|
13
|
+
<<READ(github:///resources/https%3A%2F%2Fexample.test%2Fdocument)::READ
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
The module requires protocol revision `2026-07-28`. It does not negotiate or
|
|
17
|
+
fall back to a legacy revision.
|
|
18
|
+
|
|
19
|
+
## Configuration
|
|
20
|
+
|
|
21
|
+
Configuration is daemon-owned. One `PLURNK_MCP_<server>` variable declares
|
|
22
|
+
each server; the suffix case-folds to the executor and URI authority name.
|
|
23
|
+
|
|
24
|
+
Streamable HTTP:
|
|
25
|
+
|
|
26
|
+
```text
|
|
27
|
+
PLURNK_MCP_github=https://example.test/mcp
|
|
28
|
+
PLURNK_MCP_github_HEADERS={"Authorization":"Bearer ${GITHUB_TOKEN}"}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Stdio:
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
PLURNK_MCP_local=/absolute/path/to/executable
|
|
35
|
+
PLURNK_MCP_local_ARGS=["--stdio"]
|
|
36
|
+
PLURNK_MCP_local_CWD=/absolute/working/directory
|
|
37
|
+
PLURNK_MCP_local_ENV={"TOKEN":"${LOCAL_TOKEN}"}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The stdio target is exactly one executable. Arguments are a JSON array; the
|
|
41
|
+
module never parses or invokes a shell command. `${NAME}` references read the
|
|
42
|
+
daemon's inherited environment at startup, so secrets do not need to be copied
|
|
43
|
+
into Plurnk environment files.
|
|
44
|
+
|
|
45
|
+
Portable timeout defaults and complete examples live in
|
|
46
|
+
[`.env.defaults`](./.env.defaults).
|
|
47
|
+
|
|
48
|
+
## Current surface
|
|
49
|
+
|
|
50
|
+
- `READ(server:///)` returns the live tools, resources, resource templates, and
|
|
51
|
+
prompts catalog.
|
|
52
|
+
- `EXEC[server](tool)` calls a tool with one JSON object in the body.
|
|
53
|
+
- `server:///resources` exposes the resource catalog through ordinary Plurnk
|
|
54
|
+
`FIND` and `READ`.
|
|
55
|
+
- `server:///resources/<encoded-uri>` reads a concrete MCP resource and stores
|
|
56
|
+
it as an ordinary entry, after which normal projection and slicing apply.
|
|
57
|
+
- A tool's `readOnlyHint` selects Plurnk's read effect. Unknown or mutating
|
|
58
|
+
tools retain the host effect.
|
|
59
|
+
|
|
60
|
+
Prompt retrieval, resource subscriptions, current multi-round-trip input,
|
|
61
|
+
current task methods, and OAuth/OIDC authorization are not part of this
|
|
62
|
+
vertical slice. They will use the same module and connection seams; no legacy
|
|
63
|
+
protocol surface is retained as a fallback.
|
|
64
|
+
|
|
65
|
+
## Verification
|
|
66
|
+
|
|
67
|
+
`npm test` type-checks the module and exercises exact current-version
|
|
68
|
+
negotiation, configuration, tool calls, resource reads, runtime registration,
|
|
69
|
+
and rejection of ambiguous shell and secret configuration.
|
package/SPEC.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Plurnk MCP host specification
|
|
2
|
+
|
|
3
|
+
## Current protocol boundary
|
|
4
|
+
|
|
5
|
+
- The only accepted MCP revision is `2026-07-28`.
|
|
6
|
+
- Every client connection pins that revision and verifies a modern
|
|
7
|
+
`server/discover` result before registration.
|
|
8
|
+
- Stdio servers are invoked as an executable plus an explicit argument array.
|
|
9
|
+
Shell command parsing is not part of the contract.
|
|
10
|
+
- HTTP uses Streamable HTTP. There is no legacy SSE fallback.
|
|
11
|
+
- A connection or discovery failure leaves no registered runtime.
|
|
12
|
+
- Shutdown waits for every connection attempt to settle, then closes every
|
|
13
|
+
acquired connection and reports all close failures.
|
|
14
|
+
|
|
15
|
+
## Configuration
|
|
16
|
+
|
|
17
|
+
| Variable | Contract |
|
|
18
|
+
|---|---|
|
|
19
|
+
| `PLURNK_MCP_<server>` | HTTP(S) URL or exact stdio executable |
|
|
20
|
+
| `PLURNK_MCP_<server>_ARGS` | JSON string array for stdio |
|
|
21
|
+
| `PLURNK_MCP_<server>_CWD` | Working directory for stdio |
|
|
22
|
+
| `PLURNK_MCP_<server>_ENV` | JSON string map for stdio |
|
|
23
|
+
| `PLURNK_MCP_<server>_HEADERS` | JSON string map for HTTP |
|
|
24
|
+
| `PLURNK_MCP_CONNECT_TIMEOUT` | Positive integer milliseconds |
|
|
25
|
+
| `PLURNK_MCP_REQUEST_TIMEOUT` | Positive integer milliseconds |
|
|
26
|
+
|
|
27
|
+
Server names case-fold. Duplicate names, orphan companions, transport-specific
|
|
28
|
+
companions on the wrong transport, missing environment references, and invalid
|
|
29
|
+
JSON fail startup.
|
|
30
|
+
|
|
31
|
+
## Model-facing mapping
|
|
32
|
+
|
|
33
|
+
| MCP surface | Plurnk surface |
|
|
34
|
+
|---|---|
|
|
35
|
+
| Server | `EXEC[server]` and `server://` |
|
|
36
|
+
| Tool catalog | `server:///` |
|
|
37
|
+
| Tool call | `EXEC[server](tool)` with a JSON object body |
|
|
38
|
+
| Resource catalog | `server:///resources` |
|
|
39
|
+
| Resource read | `server:///resources/<encoded-uri>` |
|
|
40
|
+
|
|
41
|
+
The executor manifest remains the owner of ordinary result coordinates. The
|
|
42
|
+
MCP resource facet claims only `/`, `/resources`, and descendants. Every other
|
|
43
|
+
path uses the standard executor-output scheme.
|
|
44
|
+
|
|
45
|
+
Tools and resources are current in this vertical slice. Cataloged prompts are
|
|
46
|
+
descriptive only. Prompt retrieval, subscriptions, multi-round-trip input,
|
|
47
|
+
tasks, and authorization remain unavailable until their current contracts are
|
|
48
|
+
implemented and covered; they do not fall back to legacy behavior.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { BaseExecutor } from "@plurnk/plurnk-execs";
|
|
2
|
+
import type { ChannelDecl, Effect, ExecArgs, ExecResult, RuntimeAvailability, RuntimeDecl } from "@plurnk/plurnk-execs";
|
|
3
|
+
import ServerConnection from "./client.ts";
|
|
4
|
+
export declare const runtimeDecl: (name: string) => RuntimeDecl;
|
|
5
|
+
export default class McpExecutor extends BaseExecutor {
|
|
6
|
+
#private;
|
|
7
|
+
constructor(metadata: {
|
|
8
|
+
runtime: string;
|
|
9
|
+
glyph: string;
|
|
10
|
+
}, connection: ServerConnection);
|
|
11
|
+
get channels(): Readonly<Record<string, ChannelDecl>>;
|
|
12
|
+
effect(target: string | null): Effect;
|
|
13
|
+
probe(signal?: AbortSignal): Promise<RuntimeAvailability>;
|
|
14
|
+
run({ runtime, command, target, signal, write, setState, }: ExecArgs): Promise<ExecResult>;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=McpExecutor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"McpExecutor.d.ts","sourceRoot":"","sources":["../src/McpExecutor.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,YAAY,EAIf,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EACR,WAAW,EACX,MAAM,EACN,QAAQ,EACR,UAAU,EACV,mBAAmB,EACnB,WAAW,EACd,MAAM,sBAAsB,CAAC;AAC9B,OAAO,gBAAgB,MAAM,aAAa,CAAC;AAI3C,eAAO,MAAM,WAAW,SAAU,MAAM,KAAG,WAiBzC,CAAC;AAKH,MAAM,CAAC,OAAO,OAAO,WAAY,SAAQ,YAAY;;IAGjD,YACI,QAAQ,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAC5C,UAAU,EAAE,gBAAgB,EAI/B;IAED,IAAI,QAAQ,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAMpD;IAEQ,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAG7C;IAEc,KAAK,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAyBvE;IAEK,GAAG,CAAC,EACN,OAAO,EACP,OAAO,EACP,MAAM,EACN,MAAM,EACN,KAAK,EACL,QAAQ,GACX,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,CA0FhC;CACJ"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { BaseExecutor, ErrorDetail, ERROR_DETAIL_LIMIT, Results, } from "@plurnk/plurnk-execs";
|
|
2
|
+
const CHANNEL = "body";
|
|
3
|
+
export const runtimeDecl = (name) => ({
|
|
4
|
+
name,
|
|
5
|
+
glyph: "🔌",
|
|
6
|
+
example: `<<EXEC[${name}](tool_name):{"argument":"value"}:EXEC`,
|
|
7
|
+
documentation: `# ${name}
|
|
8
|
+
|
|
9
|
+
This configured MCP server is available as an executable tool family and an
|
|
10
|
+
addressable resource family.
|
|
11
|
+
|
|
12
|
+
\`\`\`plurnk
|
|
13
|
+
<<READ(${name}:///):READ
|
|
14
|
+
<<EXEC[${name}](tool_name):{"argument":"value"}:EXEC
|
|
15
|
+
\`\`\`
|
|
16
|
+
|
|
17
|
+
READ returns the live catalog. Tool arguments are one JSON object. Tool results
|
|
18
|
+
are written to the operation's \`body\` channel.
|
|
19
|
+
`,
|
|
20
|
+
});
|
|
21
|
+
const message = (error) => error instanceof Error ? error.message : String(error);
|
|
22
|
+
export default class McpExecutor extends BaseExecutor {
|
|
23
|
+
#connection;
|
|
24
|
+
constructor(metadata, connection) {
|
|
25
|
+
super(metadata);
|
|
26
|
+
this.#connection = connection;
|
|
27
|
+
}
|
|
28
|
+
get channels() {
|
|
29
|
+
return {
|
|
30
|
+
[CHANNEL]: {
|
|
31
|
+
mimetype: "application/json",
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
effect(target) {
|
|
36
|
+
if (target === null || target.length === 0)
|
|
37
|
+
return "read";
|
|
38
|
+
return this.#connection.readOnly(target) ? "read" : "host";
|
|
39
|
+
}
|
|
40
|
+
async probe(signal) {
|
|
41
|
+
const detailLimit = ErrorDetail.configuredLimit();
|
|
42
|
+
if (detailLimit === null) {
|
|
43
|
+
return {
|
|
44
|
+
available: false,
|
|
45
|
+
detail: `${ERROR_DETAIL_LIMIT} must be set to a non-negative integer.`,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
const catalog = await this.#connection.catalog(signal);
|
|
50
|
+
return {
|
|
51
|
+
available: true,
|
|
52
|
+
detail: [
|
|
53
|
+
`MCP ${catalog.protocolVersion}`,
|
|
54
|
+
`${catalog.tools.length} tools`,
|
|
55
|
+
`${catalog.resources.length} resources`,
|
|
56
|
+
`${catalog.prompts.length} prompts`,
|
|
57
|
+
].join("; "),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
return {
|
|
62
|
+
available: false,
|
|
63
|
+
detail: ErrorDetail.preview(message(error), detailLimit),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
async run({ runtime, command, target, signal, write, setState, }) {
|
|
68
|
+
const fail = (code, status, detail, extensions) => {
|
|
69
|
+
setState(CHANNEL, "errored");
|
|
70
|
+
return Results.failure("executor:mcp", code, status, detail, {}, {
|
|
71
|
+
runtime,
|
|
72
|
+
stage: "mcp",
|
|
73
|
+
...extensions,
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
const detailLimit = ErrorDetail.configuredLimit();
|
|
77
|
+
if (detailLimit === null) {
|
|
78
|
+
setState(CHANNEL, "errored");
|
|
79
|
+
return ErrorDetail.invalidConfiguration("executor:mcp");
|
|
80
|
+
}
|
|
81
|
+
const body = command.trim();
|
|
82
|
+
if (target === null || target.length === 0) {
|
|
83
|
+
return fail("tool-required", 400, `MCP executor '${runtime}' requires a tool target.`, {
|
|
84
|
+
recovery: `READ ${runtime}:/// for the live catalog, then target one listed tool.`,
|
|
85
|
+
retryable: false,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
let args = {};
|
|
89
|
+
if (body.length > 0) {
|
|
90
|
+
try {
|
|
91
|
+
const parsed = JSON.parse(body);
|
|
92
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
93
|
+
throw new TypeError("tool arguments must be an object");
|
|
94
|
+
}
|
|
95
|
+
args = parsed;
|
|
96
|
+
}
|
|
97
|
+
catch (cause) {
|
|
98
|
+
return fail("invalid-tool-arguments", 400, `Arguments for MCP tool '${target}' must be one JSON object.`, {
|
|
99
|
+
tool: target,
|
|
100
|
+
retryable: false,
|
|
101
|
+
diagnostic: ErrorDetail.preview(message(cause), detailLimit),
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
try {
|
|
106
|
+
const result = await this.#connection.callTool(target, args, signal);
|
|
107
|
+
write(CHANNEL, JSON.stringify(result), "application/json");
|
|
108
|
+
if (result.isError === true) {
|
|
109
|
+
return fail("tool-reported-error", 502, `MCP tool '${target}' on '${runtime}' reported an error.`, {
|
|
110
|
+
tool: target,
|
|
111
|
+
retryable: false,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
setState(CHANNEL, "closed");
|
|
115
|
+
return { status: 200 };
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
return fail(signal.aborted ? "cancelled" : "tool-call-failed", signal.aborted ? 499 : 502, signal.aborted
|
|
119
|
+
? `MCP tool '${target}' on '${runtime}' was cancelled.`
|
|
120
|
+
: `MCP tool '${target}' on '${runtime}' failed: ${ErrorDetail.preview(message(error), detailLimit)}.`, {
|
|
121
|
+
tool: target,
|
|
122
|
+
retryable: !signal.aborted,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=McpExecutor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"McpExecutor.js","sourceRoot":"","sources":["../src/McpExecutor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type EntryReadResult, type EntryFindResult, type FindStatement, type ReadStatement, type SchemeCtx } from "@plurnk/plurnk-schemes";
|
|
2
|
+
import ServerConnection from "./client.ts";
|
|
3
|
+
export default class McpResources {
|
|
4
|
+
#private;
|
|
5
|
+
constructor(server: string, connection: ServerConnection);
|
|
6
|
+
claims(pathname: string): boolean;
|
|
7
|
+
read(statement: ReadStatement, ctx: SchemeCtx): Promise<EntryReadResult>;
|
|
8
|
+
find(statement: FindStatement, ctx: SchemeCtx): Promise<EntryFindResult>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=McpResources.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"McpResources.d.ts","sourceRoot":"","sources":["../src/McpResources.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,SAAS,EACjB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,gBAAgB,MAAM,aAAa,CAAC;AAyF3C,MAAM,CAAC,OAAO,OAAO,YAAY;;IAI7B,YAAY,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,gBAAgB,EAGvD;IAED,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAIhC;IAgEK,IAAI,CAAC,SAAS,EAAE,aAAa,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,eAAe,CAAC,CA4B7E;IAEK,IAAI,CAAC,SAAS,EAAE,aAAa,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,eAAe,CAAC,CAgB7E;CACJ"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { Results, } from "@plurnk/plurnk-schemes";
|
|
2
|
+
const ROOT = "/";
|
|
3
|
+
const RESOURCES = "/resources";
|
|
4
|
+
const RESOURCE_PREFIX = `${RESOURCES}/`;
|
|
5
|
+
const RESOURCE_TAG = "mcp-resource";
|
|
6
|
+
const CATALOG_TAG = "mcp-resource-catalog";
|
|
7
|
+
class ResourceAddressError extends Error {
|
|
8
|
+
}
|
|
9
|
+
const resourcePath = (uri) => `${RESOURCE_PREFIX}${encodeURIComponent(uri)}`;
|
|
10
|
+
const readFailure = (server, code, status, detail, extensions) => Results.failure("scheme:mcp", code, status, detail, {
|
|
11
|
+
content: null,
|
|
12
|
+
mimetype: null,
|
|
13
|
+
channel: null,
|
|
14
|
+
}, {
|
|
15
|
+
server,
|
|
16
|
+
stage: "mcp-resource",
|
|
17
|
+
...extensions,
|
|
18
|
+
});
|
|
19
|
+
const findFailure = (server, code, status, detail, extensions) => Results.failure("scheme:mcp", code, status, detail, {
|
|
20
|
+
content: null,
|
|
21
|
+
mimetype: null,
|
|
22
|
+
results: [],
|
|
23
|
+
itemsTokenTotal: 0,
|
|
24
|
+
pathnames: [],
|
|
25
|
+
matches: [],
|
|
26
|
+
}, {
|
|
27
|
+
server,
|
|
28
|
+
stage: "mcp-resource",
|
|
29
|
+
...extensions,
|
|
30
|
+
});
|
|
31
|
+
const resourceBody = (result) => {
|
|
32
|
+
if (result.contents.length === 1 && "text" in result.contents[0]) {
|
|
33
|
+
const value = result.contents[0];
|
|
34
|
+
return {
|
|
35
|
+
content: value.text,
|
|
36
|
+
mimetype: value.mimeType ?? "text/plain",
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
content: JSON.stringify(result),
|
|
41
|
+
mimetype: "application/json",
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
const catalogEntry = (content, tags) => ({
|
|
45
|
+
channels: {
|
|
46
|
+
body: {
|
|
47
|
+
content,
|
|
48
|
+
mimetype: "application/json",
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
tags,
|
|
52
|
+
});
|
|
53
|
+
export default class McpResources {
|
|
54
|
+
#server;
|
|
55
|
+
#connection;
|
|
56
|
+
constructor(server, connection) {
|
|
57
|
+
this.#server = server;
|
|
58
|
+
this.#connection = connection;
|
|
59
|
+
}
|
|
60
|
+
claims(pathname) {
|
|
61
|
+
return pathname === ROOT
|
|
62
|
+
|| pathname === RESOURCES
|
|
63
|
+
|| pathname.startsWith(RESOURCE_PREFIX);
|
|
64
|
+
}
|
|
65
|
+
async #materializeCatalog(ctx) {
|
|
66
|
+
const catalog = await this.#connection.catalog(ctx.signal);
|
|
67
|
+
await ctx.entries.write(ROOT, catalogEntry(JSON.stringify({
|
|
68
|
+
...catalog,
|
|
69
|
+
resources: catalog.resources.map((resource) => ({
|
|
70
|
+
...resource,
|
|
71
|
+
address: `${this.#server}://${resourcePath(resource.uri)}`,
|
|
72
|
+
})),
|
|
73
|
+
}), ["mcp-catalog"]));
|
|
74
|
+
await ctx.entries.write(RESOURCES, catalogEntry(JSON.stringify({
|
|
75
|
+
resources: catalog.resources.map((resource) => ({
|
|
76
|
+
...resource,
|
|
77
|
+
address: `${this.#server}://${resourcePath(resource.uri)}`,
|
|
78
|
+
})),
|
|
79
|
+
resourceTemplates: catalog.resourceTemplates,
|
|
80
|
+
}), ["mcp-resource-index"]));
|
|
81
|
+
await Promise.all(catalog.resources.map(async (resource) => {
|
|
82
|
+
const pathname = resourcePath(resource.uri);
|
|
83
|
+
const existing = await ctx.entries.read(pathname);
|
|
84
|
+
if (existing.entry?.tags.includes(RESOURCE_TAG) === true)
|
|
85
|
+
return;
|
|
86
|
+
await ctx.entries.write(pathname, catalogEntry(JSON.stringify({
|
|
87
|
+
...resource,
|
|
88
|
+
address: `${this.#server}://${pathname}`,
|
|
89
|
+
}), [CATALOG_TAG]));
|
|
90
|
+
}));
|
|
91
|
+
}
|
|
92
|
+
async #materializeResource(pathname, ctx) {
|
|
93
|
+
const encoded = pathname.slice(RESOURCE_PREFIX.length);
|
|
94
|
+
if (encoded.length === 0 || encoded.includes("/")) {
|
|
95
|
+
throw new ResourceAddressError(`Invalid MCP resource address '${pathname}'.`);
|
|
96
|
+
}
|
|
97
|
+
let uri;
|
|
98
|
+
try {
|
|
99
|
+
uri = decodeURIComponent(encoded);
|
|
100
|
+
}
|
|
101
|
+
catch (cause) {
|
|
102
|
+
throw new ResourceAddressError(`Invalid encoded MCP resource address '${pathname}'.`, { cause });
|
|
103
|
+
}
|
|
104
|
+
const body = resourceBody(await this.#connection.readResource(uri, ctx.signal));
|
|
105
|
+
await ctx.entries.write(pathname, {
|
|
106
|
+
channels: {
|
|
107
|
+
body: {
|
|
108
|
+
content: body.content,
|
|
109
|
+
mimetype: body.mimetype,
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
tags: [RESOURCE_TAG],
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
async read(statement, ctx) {
|
|
116
|
+
const pathname = statement.target?.kind === "url"
|
|
117
|
+
? statement.target.pathname ?? ROOT
|
|
118
|
+
: ROOT;
|
|
119
|
+
try {
|
|
120
|
+
const exactResource = pathname.startsWith(RESOURCE_PREFIX)
|
|
121
|
+
&& !/[*?[\]{}]/.test(pathname);
|
|
122
|
+
if (exactResource) {
|
|
123
|
+
await this.#materializeResource(pathname, ctx);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
await this.#materializeCatalog(ctx);
|
|
127
|
+
}
|
|
128
|
+
return await ctx.entries.operations.read(statement);
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
const invalidAddress = error instanceof ResourceAddressError;
|
|
132
|
+
return readFailure(this.#server, invalidAddress ? "resource-address-invalid" : "resource-read-failed", invalidAddress ? 400 : 502, invalidAddress
|
|
133
|
+
? `The requested MCP resource address for '${this.#server}' is invalid.`
|
|
134
|
+
: `MCP server '${this.#server}' could not read the requested resource.`, {
|
|
135
|
+
diagnostic: error instanceof Error ? error.message : String(error),
|
|
136
|
+
retryable: !invalidAddress,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
async find(statement, ctx) {
|
|
141
|
+
try {
|
|
142
|
+
await this.#materializeCatalog(ctx);
|
|
143
|
+
return await ctx.entries.operations.find(statement);
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
return findFailure(this.#server, "resource-find-failed", 502, `MCP server '${this.#server}' could not list its resources.`, {
|
|
147
|
+
diagnostic: error instanceof Error ? error.message : String(error),
|
|
148
|
+
retryable: true,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=McpResources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"McpResources.js","sourceRoot":"","sources":["../src/McpResources.ts"],"names":[],"mappings":"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"}
|
package/dist/Module.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { RuntimeAvailability, RuntimeDecl } from "@plurnk/plurnk-execs";
|
|
2
|
+
import type { FindStatement, ReadStatement, SchemeCtx, SchemeResult } from "@plurnk/plurnk-schemes";
|
|
3
|
+
import McpExecutor from "./McpExecutor.ts";
|
|
4
|
+
interface RuntimeSchemeFacet {
|
|
5
|
+
claims(pathname: string): boolean;
|
|
6
|
+
read?(statement: ReadStatement, ctx: SchemeCtx): Promise<SchemeResult>;
|
|
7
|
+
find?(statement: FindStatement, ctx: SchemeCtx): Promise<SchemeResult>;
|
|
8
|
+
}
|
|
9
|
+
interface ModuleSetupSeam {
|
|
10
|
+
registerRuntime(registration: {
|
|
11
|
+
readonly namespaceOwner: string;
|
|
12
|
+
readonly decl: RuntimeDecl;
|
|
13
|
+
readonly executor: McpExecutor;
|
|
14
|
+
readonly availability: RuntimeAvailability;
|
|
15
|
+
readonly scheme?: RuntimeSchemeFacet;
|
|
16
|
+
}): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
export interface ModuleOptions {
|
|
19
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
20
|
+
}
|
|
21
|
+
export default class Module {
|
|
22
|
+
#private;
|
|
23
|
+
static init(options?: ModuleOptions): Module;
|
|
24
|
+
private constructor();
|
|
25
|
+
setup(seam: ModuleSetupSeam): Promise<void>;
|
|
26
|
+
close(): Promise<void>;
|
|
27
|
+
}
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=Module.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Module.d.ts","sourceRoot":"","sources":["../src/Module.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACR,mBAAmB,EACnB,WAAW,EACd,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EACR,aAAa,EACb,aAAa,EACb,SAAS,EACT,YAAY,EACf,MAAM,wBAAwB,CAAC;AAGhC,OAAO,WAA4B,MAAM,kBAAkB,CAAC;AAG5D,UAAU,kBAAkB;IACxB,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IAClC,IAAI,CAAC,CAAC,SAAS,EAAE,aAAa,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IACvE,IAAI,CAAC,CAAC,SAAS,EAAE,aAAa,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CAC1E;AAED,UAAU,eAAe;IACrB,eAAe,CAAC,YAAY,EAAE;QAC1B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;QAChC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;QAC3B,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;QAC/B,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAAC;QAC3C,QAAQ,CAAC,MAAM,CAAC,EAAE,kBAAkB,CAAC;KACxC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC1B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACpC;AAED,MAAM,CAAC,OAAO,OAAO,MAAM;;IAIvB,MAAM,CAAC,IAAI,CAAC,OAAO,GAAE,aAAkB,GAAG,MAAM,CAE/C;IAED,OAAO,eAEN;IAEK,KAAK,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAiChD;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAU3B;CACJ"}
|
package/dist/Module.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import ServerConnection from "./client.js";
|
|
2
|
+
import { serverConfig, serverNames } from "./config.js";
|
|
3
|
+
import McpExecutor, { runtimeDecl } from "./McpExecutor.js";
|
|
4
|
+
import McpResources from "./McpResources.js";
|
|
5
|
+
export default class Module {
|
|
6
|
+
#env;
|
|
7
|
+
#connections = new Map();
|
|
8
|
+
static init(options = {}) {
|
|
9
|
+
return new Module(options.env ?? process.env);
|
|
10
|
+
}
|
|
11
|
+
constructor(environ) {
|
|
12
|
+
this.#env = environ;
|
|
13
|
+
}
|
|
14
|
+
async setup(seam) {
|
|
15
|
+
const results = await Promise.allSettled(serverNames(this.#env).map(async (name) => {
|
|
16
|
+
const config = serverConfig(name, this.#env);
|
|
17
|
+
if (config === null)
|
|
18
|
+
throw new Error(`MCP server '${name}' disappeared during configuration.`);
|
|
19
|
+
const connection = new ServerConnection(config, this.#env);
|
|
20
|
+
this.#connections.set(name, connection);
|
|
21
|
+
const decl = runtimeDecl(name);
|
|
22
|
+
const executor = new McpExecutor({
|
|
23
|
+
runtime: name,
|
|
24
|
+
glyph: decl.glyph ?? "",
|
|
25
|
+
}, connection);
|
|
26
|
+
return {
|
|
27
|
+
namespaceOwner: "@plurnk/plurnk-mcp",
|
|
28
|
+
decl,
|
|
29
|
+
executor,
|
|
30
|
+
availability: await executor.probe(),
|
|
31
|
+
scheme: new McpResources(name, connection),
|
|
32
|
+
};
|
|
33
|
+
}));
|
|
34
|
+
const errors = results
|
|
35
|
+
.filter((result) => result.status === "rejected")
|
|
36
|
+
.map((result) => result.reason);
|
|
37
|
+
if (errors.length > 0)
|
|
38
|
+
throw new AggregateError(errors, "MCP module setup failed");
|
|
39
|
+
const registrations = results.flatMap((result) => result.status === "fulfilled" ? [result.value] : []);
|
|
40
|
+
for (const registration of registrations) {
|
|
41
|
+
await seam.registerRuntime(registration);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async close() {
|
|
45
|
+
const connections = [...this.#connections.values()];
|
|
46
|
+
this.#connections.clear();
|
|
47
|
+
const results = await Promise.allSettled(connections.map((connection) => connection.close()));
|
|
48
|
+
const errors = results
|
|
49
|
+
.filter((result) => result.status === "rejected")
|
|
50
|
+
.map((result) => result.reason);
|
|
51
|
+
if (errors.length > 0)
|
|
52
|
+
throw new AggregateError(errors, "MCP connection shutdown failed");
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=Module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Module.js","sourceRoot":"","sources":["../src/Module.ts"],"names":[],"mappings":"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"}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Client, type CallToolResult, type DiscoverResult, type ReadResourceResult, type Tool } from "@modelcontextprotocol/client";
|
|
2
|
+
import { type ServerConfig } from "./config.ts";
|
|
3
|
+
export declare const MCP_PROTOCOL_VERSION = "2026-07-28";
|
|
4
|
+
export interface ServerCatalog {
|
|
5
|
+
readonly protocolVersion: typeof MCP_PROTOCOL_VERSION;
|
|
6
|
+
readonly server: ReturnType<Client["getServerVersion"]>;
|
|
7
|
+
readonly capabilities: DiscoverResult["capabilities"];
|
|
8
|
+
readonly tools: Awaited<ReturnType<Client["listTools"]>>["tools"];
|
|
9
|
+
readonly resources: Awaited<ReturnType<Client["listResources"]>>["resources"];
|
|
10
|
+
readonly resourceTemplates: Awaited<ReturnType<Client["listResourceTemplates"]>>["resourceTemplates"];
|
|
11
|
+
readonly prompts: Awaited<ReturnType<Client["listPrompts"]>>["prompts"];
|
|
12
|
+
}
|
|
13
|
+
export default class ServerConnection {
|
|
14
|
+
#private;
|
|
15
|
+
constructor(config: ServerConfig, environ?: NodeJS.ProcessEnv);
|
|
16
|
+
connect(): Promise<Client>;
|
|
17
|
+
readOnly(tool: string): boolean;
|
|
18
|
+
tools(signal?: AbortSignal): Promise<Tool[]>;
|
|
19
|
+
catalog(signal?: AbortSignal): Promise<ServerCatalog>;
|
|
20
|
+
resources(signal?: AbortSignal): Promise<{
|
|
21
|
+
resources: ServerCatalog["resources"];
|
|
22
|
+
resourceTemplates: ServerCatalog["resourceTemplates"];
|
|
23
|
+
}>;
|
|
24
|
+
callTool(name: string, args: Record<string, unknown>, signal?: AbortSignal): Promise<CallToolResult>;
|
|
25
|
+
readResource(uri: string, signal?: AbortSignal): Promise<ReadResourceResult>;
|
|
26
|
+
close(): Promise<void>;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,MAAM,EAEN,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,IAAI,EACZ,MAAM,8BAA8B,CAAC;AAMtC,OAAO,EAGH,KAAK,YAAY,EACpB,MAAM,aAAa,CAAC;AAErB,eAAO,MAAM,oBAAoB,eAAe,CAAC;AAEjD,MAAM,WAAW,aAAa;IAC1B,QAAQ,CAAC,eAAe,EAAE,OAAO,oBAAoB,CAAC;IACtD,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC;IACxD,QAAQ,CAAC,YAAY,EAAE,cAAc,CAAC,cAAc,CAAC,CAAC;IACtD,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IAClE,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IAC9E,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC;IACtG,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;CAC3E;AAkED,MAAM,CAAC,OAAO,OAAO,gBAAgB;;IAMjC,YAAY,MAAM,EAAE,YAAY,EAAE,OAAO,GAAE,MAAM,CAAC,UAAwB,EAGzE;IAED,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,CAQzB;IAED,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE9B;IAEK,KAAK,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAOjD;IAEK,OAAO,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,CA2B1D;IAEK,SAAS,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC;QAC3C,SAAS,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC;QACtC,iBAAiB,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAC;KACzD,CAAC,CAmBD;IAEK,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC,CAKzG;IAEK,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAKjF;IASK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAI3B;CACJ"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { Client, StreamableHTTPClientTransport, } from "@modelcontextprotocol/client";
|
|
2
|
+
import { StdioClientTransport, getDefaultEnvironment, } from "@modelcontextprotocol/client/stdio";
|
|
3
|
+
import packageJson from "../package.json" with { type: "json" };
|
|
4
|
+
import { connectTimeoutMs, requestTimeoutMs, } from "./config.js";
|
|
5
|
+
export const MCP_PROTOCOL_VERSION = "2026-07-28";
|
|
6
|
+
const openTransport = (config) => {
|
|
7
|
+
if (config.transport === "http") {
|
|
8
|
+
return new StreamableHTTPClientTransport(new URL(config.url), config.headers === undefined
|
|
9
|
+
? undefined
|
|
10
|
+
: { requestInit: { headers: config.headers } });
|
|
11
|
+
}
|
|
12
|
+
return new StdioClientTransport({
|
|
13
|
+
command: config.command,
|
|
14
|
+
args: config.args,
|
|
15
|
+
cwd: config.cwd,
|
|
16
|
+
env: {
|
|
17
|
+
...getDefaultEnvironment(),
|
|
18
|
+
...config.env,
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
const openClient = async (config, environ) => {
|
|
23
|
+
const client = new Client({
|
|
24
|
+
name: packageJson.name,
|
|
25
|
+
version: packageJson.version,
|
|
26
|
+
}, {
|
|
27
|
+
versionNegotiation: {
|
|
28
|
+
mode: { pin: MCP_PROTOCOL_VERSION },
|
|
29
|
+
},
|
|
30
|
+
inputRequired: {
|
|
31
|
+
autoFulfill: false,
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
try {
|
|
35
|
+
await client.connect(openTransport(config), {
|
|
36
|
+
timeout: connectTimeoutMs(environ),
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
catch (cause) {
|
|
40
|
+
try {
|
|
41
|
+
await client.close();
|
|
42
|
+
}
|
|
43
|
+
catch (closeCause) {
|
|
44
|
+
throw new AggregateError([cause, closeCause], `MCP ${MCP_PROTOCOL_VERSION} connection and cleanup failed.`);
|
|
45
|
+
}
|
|
46
|
+
throw new Error(`MCP ${MCP_PROTOCOL_VERSION} connection failed.`, { cause });
|
|
47
|
+
}
|
|
48
|
+
if (client.getProtocolEra() !== "modern"
|
|
49
|
+
|| client.getNegotiatedProtocolVersion() !== MCP_PROTOCOL_VERSION
|
|
50
|
+
|| client.getDiscoverResult() === undefined) {
|
|
51
|
+
await client.close();
|
|
52
|
+
throw new Error(`MCP server did not negotiate required revision ${MCP_PROTOCOL_VERSION}.`);
|
|
53
|
+
}
|
|
54
|
+
return client;
|
|
55
|
+
};
|
|
56
|
+
export default class ServerConnection {
|
|
57
|
+
#config;
|
|
58
|
+
#environ;
|
|
59
|
+
#client;
|
|
60
|
+
#toolHints = new Map();
|
|
61
|
+
constructor(config, environ = process.env) {
|
|
62
|
+
this.#config = config;
|
|
63
|
+
this.#environ = environ;
|
|
64
|
+
}
|
|
65
|
+
connect() {
|
|
66
|
+
if (this.#client !== undefined)
|
|
67
|
+
return this.#client;
|
|
68
|
+
const pending = openClient(this.#config, this.#environ).catch((cause) => {
|
|
69
|
+
if (this.#client === pending)
|
|
70
|
+
this.#client = undefined;
|
|
71
|
+
throw cause;
|
|
72
|
+
});
|
|
73
|
+
this.#client = pending;
|
|
74
|
+
return pending;
|
|
75
|
+
}
|
|
76
|
+
readOnly(tool) {
|
|
77
|
+
return this.#toolHints.get(tool) === true;
|
|
78
|
+
}
|
|
79
|
+
async tools(signal) {
|
|
80
|
+
const client = await this.connect();
|
|
81
|
+
const { tools } = await client.listTools(undefined, this.#requestOptions(signal));
|
|
82
|
+
this.#toolHints = new Map(tools.map((tool) => [tool.name, tool.annotations?.readOnlyHint === true]));
|
|
83
|
+
return tools;
|
|
84
|
+
}
|
|
85
|
+
async catalog(signal) {
|
|
86
|
+
const client = await this.connect();
|
|
87
|
+
const discover = client.getDiscoverResult();
|
|
88
|
+
if (discover === undefined)
|
|
89
|
+
throw new Error("Modern MCP connection omitted its discovery result.");
|
|
90
|
+
const [tools, resources, resourceTemplates, prompts] = await Promise.all([
|
|
91
|
+
discover.capabilities.tools === undefined
|
|
92
|
+
? Promise.resolve([])
|
|
93
|
+
: this.tools(signal),
|
|
94
|
+
discover.capabilities.resources === undefined
|
|
95
|
+
? Promise.resolve([])
|
|
96
|
+
: client.listResources(undefined, this.#requestOptions(signal)).then((result) => result.resources),
|
|
97
|
+
discover.capabilities.resources === undefined
|
|
98
|
+
? Promise.resolve([])
|
|
99
|
+
: client.listResourceTemplates(undefined, this.#requestOptions(signal)).then((result) => result.resourceTemplates),
|
|
100
|
+
discover.capabilities.prompts === undefined
|
|
101
|
+
? Promise.resolve([])
|
|
102
|
+
: client.listPrompts(undefined, this.#requestOptions(signal)).then((result) => result.prompts),
|
|
103
|
+
]);
|
|
104
|
+
return {
|
|
105
|
+
protocolVersion: MCP_PROTOCOL_VERSION,
|
|
106
|
+
server: client.getServerVersion(),
|
|
107
|
+
capabilities: discover.capabilities,
|
|
108
|
+
tools,
|
|
109
|
+
resources,
|
|
110
|
+
resourceTemplates,
|
|
111
|
+
prompts,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
async resources(signal) {
|
|
115
|
+
const client = await this.connect();
|
|
116
|
+
const discover = client.getDiscoverResult();
|
|
117
|
+
if (discover?.capabilities.resources === undefined) {
|
|
118
|
+
return {
|
|
119
|
+
resources: [],
|
|
120
|
+
resourceTemplates: [],
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
const [resources, resourceTemplates] = await Promise.all([
|
|
124
|
+
client.listResources(undefined, this.#requestOptions(signal))
|
|
125
|
+
.then((result) => result.resources),
|
|
126
|
+
client.listResourceTemplates(undefined, this.#requestOptions(signal))
|
|
127
|
+
.then((result) => result.resourceTemplates),
|
|
128
|
+
]);
|
|
129
|
+
return {
|
|
130
|
+
resources,
|
|
131
|
+
resourceTemplates,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
async callTool(name, args, signal) {
|
|
135
|
+
return (await this.connect()).callTool({ name, arguments: args }, this.#requestOptions(signal));
|
|
136
|
+
}
|
|
137
|
+
async readResource(uri, signal) {
|
|
138
|
+
return (await this.connect()).readResource({ uri }, this.#requestOptions(signal));
|
|
139
|
+
}
|
|
140
|
+
#requestOptions(signal) {
|
|
141
|
+
return {
|
|
142
|
+
signal,
|
|
143
|
+
timeout: requestTimeoutMs(this.#environ),
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
async close() {
|
|
147
|
+
const client = this.#client;
|
|
148
|
+
this.#client = undefined;
|
|
149
|
+
if (client !== undefined)
|
|
150
|
+
await (await client).close();
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface StdioServerConfig {
|
|
2
|
+
readonly transport: "stdio";
|
|
3
|
+
readonly command: string;
|
|
4
|
+
readonly args: string[];
|
|
5
|
+
readonly cwd?: string;
|
|
6
|
+
readonly env?: Record<string, string>;
|
|
7
|
+
}
|
|
8
|
+
export interface HttpServerConfig {
|
|
9
|
+
readonly transport: "http";
|
|
10
|
+
readonly url: string;
|
|
11
|
+
readonly headers?: Record<string, string>;
|
|
12
|
+
}
|
|
13
|
+
export type ServerConfig = StdioServerConfig | HttpServerConfig;
|
|
14
|
+
export declare const serverNames: (environ?: NodeJS.ProcessEnv) => string[];
|
|
15
|
+
export declare const serverConfig: (name: string, environ?: NodeJS.ProcessEnv) => ServerConfig | null;
|
|
16
|
+
export declare const connectTimeoutMs: (environ?: NodeJS.ProcessEnv) => number;
|
|
17
|
+
export declare const requestTimeoutMs: (environ?: NodeJS.ProcessEnv) => number;
|
|
18
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,iBAAiB;IAC9B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IACxB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzC;AAED,MAAM,WAAW,gBAAgB;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7C;AAED,MAAM,MAAM,YAAY,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;AA2FhE,eAAO,MAAM,WAAW,aAAa,MAAM,CAAC,UAAU,KAAiB,MAAM,EACjB,CAAC;AAE7D,eAAO,MAAM,YAAY,SACf,MAAM,YACH,MAAM,CAAC,UAAU,KAC3B,YAAY,GAAG,IAiCjB,CAAC;AAEF,eAAO,MAAM,gBAAgB,aAAa,MAAM,CAAC,UAAU,KAAiB,MAO3E,CAAC;AAEF,eAAO,MAAM,gBAAgB,aAAa,MAAM,CAAC,UAAU,KAAiB,MAO3E,CAAC"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
const PREFIX = "PLURNK_MCP_";
|
|
2
|
+
const COMPANION_SUFFIXES = ["_args", "_cwd", "_env", "_headers"];
|
|
3
|
+
const CONTROL_KEYS = new Set(["connect_timeout", "request_timeout"]);
|
|
4
|
+
const ENV_REFERENCE = /\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g;
|
|
5
|
+
const parseEnvironment = (environ) => {
|
|
6
|
+
const targets = new Map();
|
|
7
|
+
const companions = new Map();
|
|
8
|
+
for (const [key, value] of Object.entries(environ)) {
|
|
9
|
+
if (value === undefined || !key.startsWith(PREFIX))
|
|
10
|
+
continue;
|
|
11
|
+
const suffix = key.slice(PREFIX.length);
|
|
12
|
+
if (suffix.length === 0)
|
|
13
|
+
continue;
|
|
14
|
+
const folded = suffix.toLowerCase();
|
|
15
|
+
if (CONTROL_KEYS.has(folded))
|
|
16
|
+
continue;
|
|
17
|
+
const companion = COMPANION_SUFFIXES.find((candidate) => folded.endsWith(candidate));
|
|
18
|
+
if (companion !== undefined) {
|
|
19
|
+
const name = folded.slice(0, -companion.length);
|
|
20
|
+
const bySuffix = companions.get(name) ?? new Map();
|
|
21
|
+
if (bySuffix.has(companion)) {
|
|
22
|
+
throw new Error(`Duplicate MCP server companion for '${name}${companion}'.`);
|
|
23
|
+
}
|
|
24
|
+
bySuffix.set(companion, value);
|
|
25
|
+
companions.set(name, bySuffix);
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
if (targets.has(folded)) {
|
|
29
|
+
throw new Error(`Duplicate MCP server '${folded}': multiple ${PREFIX}* keys case-fold to the same name.`);
|
|
30
|
+
}
|
|
31
|
+
targets.set(folded, value);
|
|
32
|
+
}
|
|
33
|
+
for (const name of companions.keys()) {
|
|
34
|
+
if (!targets.has(name))
|
|
35
|
+
throw new Error(`MCP server companion '${name}' has no ${PREFIX}<server> target.`);
|
|
36
|
+
}
|
|
37
|
+
return { targets, companions };
|
|
38
|
+
};
|
|
39
|
+
const expandReferences = (value, environ, field) => value.replaceAll(ENV_REFERENCE, (_match, name) => {
|
|
40
|
+
const resolved = environ[name];
|
|
41
|
+
if (resolved === undefined)
|
|
42
|
+
throw new Error(`${field} references missing environment variable ${name}.`);
|
|
43
|
+
return resolved;
|
|
44
|
+
});
|
|
45
|
+
const jsonStrings = (raw, field, environ) => {
|
|
46
|
+
if (raw === undefined || raw.length === 0)
|
|
47
|
+
return [];
|
|
48
|
+
let parsed;
|
|
49
|
+
try {
|
|
50
|
+
parsed = JSON.parse(raw);
|
|
51
|
+
}
|
|
52
|
+
catch (cause) {
|
|
53
|
+
throw new Error(`${field} must be a JSON array of strings.`, { cause });
|
|
54
|
+
}
|
|
55
|
+
if (!Array.isArray(parsed) || !parsed.every((value) => typeof value === "string")) {
|
|
56
|
+
throw new Error(`${field} must be a JSON array of strings.`);
|
|
57
|
+
}
|
|
58
|
+
return parsed.map((value) => expandReferences(value, environ, field));
|
|
59
|
+
};
|
|
60
|
+
const jsonRecord = (raw, field, environ) => {
|
|
61
|
+
if (raw === undefined || raw.length === 0)
|
|
62
|
+
return undefined;
|
|
63
|
+
let parsed;
|
|
64
|
+
try {
|
|
65
|
+
parsed = JSON.parse(raw);
|
|
66
|
+
}
|
|
67
|
+
catch (cause) {
|
|
68
|
+
throw new Error(`${field} must be a JSON object with string values.`, { cause });
|
|
69
|
+
}
|
|
70
|
+
if (typeof parsed !== "object"
|
|
71
|
+
|| parsed === null
|
|
72
|
+
|| Array.isArray(parsed)
|
|
73
|
+
|| !Object.values(parsed).every((value) => typeof value === "string")) {
|
|
74
|
+
throw new Error(`${field} must be a JSON object with string values.`);
|
|
75
|
+
}
|
|
76
|
+
return Object.fromEntries(Object.entries(parsed).map(([key, value]) => [
|
|
77
|
+
key,
|
|
78
|
+
expandReferences(value, environ, field),
|
|
79
|
+
]));
|
|
80
|
+
};
|
|
81
|
+
export const serverNames = (environ = process.env) => [...parseEnvironment(environ).targets.keys()].toSorted();
|
|
82
|
+
export const serverConfig = (name, environ = process.env) => {
|
|
83
|
+
const { targets, companions } = parseEnvironment(environ);
|
|
84
|
+
const folded = name.toLowerCase();
|
|
85
|
+
const target = targets.get(folded);
|
|
86
|
+
if (target === undefined)
|
|
87
|
+
return null;
|
|
88
|
+
if (target.length === 0)
|
|
89
|
+
throw new Error(`${PREFIX}${folded} must not be empty.`);
|
|
90
|
+
const fields = companions.get(folded);
|
|
91
|
+
const fieldName = (suffix) => `${PREFIX}${folded.toUpperCase()}${suffix.toUpperCase()}`;
|
|
92
|
+
if (/^https?:\/\//i.test(target)) {
|
|
93
|
+
if (fields?.has("_args") || fields?.has("_cwd") || fields?.has("_env")) {
|
|
94
|
+
throw new Error(`HTTP MCP server '${folded}' may declare only a _HEADERS companion.`);
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
transport: "http",
|
|
98
|
+
url: target,
|
|
99
|
+
headers: jsonRecord(fields?.get("_headers"), fieldName("_headers"), environ),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
if (/\s/.test(target)) {
|
|
103
|
+
throw new Error(`${PREFIX}${folded} must contain one executable; put arguments in ${fieldName("_args")}.`);
|
|
104
|
+
}
|
|
105
|
+
if (fields?.has("_headers")) {
|
|
106
|
+
throw new Error(`stdio MCP server '${folded}' may not declare a _HEADERS companion.`);
|
|
107
|
+
}
|
|
108
|
+
return {
|
|
109
|
+
transport: "stdio",
|
|
110
|
+
command: target,
|
|
111
|
+
args: jsonStrings(fields?.get("_args"), fieldName("_args"), environ),
|
|
112
|
+
cwd: fields?.has("_cwd")
|
|
113
|
+
? expandReferences(fields.get("_cwd"), environ, fieldName("_cwd"))
|
|
114
|
+
: undefined,
|
|
115
|
+
env: jsonRecord(fields?.get("_env"), fieldName("_env"), environ),
|
|
116
|
+
};
|
|
117
|
+
};
|
|
118
|
+
export const connectTimeoutMs = (environ = process.env) => {
|
|
119
|
+
const raw = environ.PLURNK_MCP_CONNECT_TIMEOUT;
|
|
120
|
+
const value = Number(raw);
|
|
121
|
+
if (!Number.isInteger(value) || value < 1) {
|
|
122
|
+
throw new Error(`PLURNK_MCP_CONNECT_TIMEOUT must be a positive integer; got ${JSON.stringify(raw)}.`);
|
|
123
|
+
}
|
|
124
|
+
return value;
|
|
125
|
+
};
|
|
126
|
+
export const requestTimeoutMs = (environ = process.env) => {
|
|
127
|
+
const raw = environ.PLURNK_MCP_REQUEST_TIMEOUT;
|
|
128
|
+
const value = Number(raw);
|
|
129
|
+
if (!Number.isInteger(value) || value < 1) {
|
|
130
|
+
throw new Error(`PLURNK_MCP_REQUEST_TIMEOUT must be a positive integer; got ${JSON.stringify(raw)}.`);
|
|
131
|
+
}
|
|
132
|
+
return value;
|
|
133
|
+
};
|
|
134
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { default as Module } from "./Module.ts";
|
|
2
|
+
export { default } from "./Module.ts";
|
|
3
|
+
export { MCP_PROTOCOL_VERSION } from "./client.ts";
|
|
4
|
+
export { connectTimeoutMs, requestTimeoutMs, serverConfig, serverNames, } from "./config.ts";
|
|
5
|
+
export type { HttpServerConfig, ServerConfig, StdioServerConfig, } from "./config.ts";
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EACH,gBAAgB,EAChB,gBAAgB,EAChB,YAAY,EACZ,WAAW,GACd,MAAM,aAAa,CAAC;AACrB,YAAY,EACR,gBAAgB,EAChB,YAAY,EACZ,iBAAiB,GACpB,MAAM,aAAa,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { default as Module } from "./Module.js";
|
|
2
|
+
export { default } from "./Module.js";
|
|
3
|
+
export { MCP_PROTOCOL_VERSION } from "./client.js";
|
|
4
|
+
export { connectTimeoutMs, requestTimeoutMs, serverConfig, serverNames, } from "./config.js";
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EACH,gBAAgB,EAChB,gBAAgB,EAChB,YAAY,EACZ,WAAW,GACd,MAAM,aAAa,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@plurnk/plurnk-mcp",
|
|
3
|
+
"version": "1.4.0",
|
|
4
|
+
"description": "Current Model Context Protocol host module for Plurnk.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"plurnk",
|
|
7
|
+
"exec",
|
|
8
|
+
"runtime",
|
|
9
|
+
"executor",
|
|
10
|
+
"mcp",
|
|
11
|
+
"model-context-protocol"
|
|
12
|
+
],
|
|
13
|
+
"homepage": "https://github.com/plurnk/plurnk-service/tree/main/plurnk-mcp#readme",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://repo.possumtech.com/plurnk/plurnk-service/issues"
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/plurnk/plurnk-service.git",
|
|
20
|
+
"directory": "plurnk-mcp"
|
|
21
|
+
},
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=26"
|
|
24
|
+
},
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"author": "@wikitopian",
|
|
27
|
+
"type": "module",
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public"
|
|
30
|
+
},
|
|
31
|
+
"exports": {
|
|
32
|
+
".": {
|
|
33
|
+
"plurnk-dev": "./src/index.ts",
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
|
+
"default": "./dist/index.js"
|
|
36
|
+
},
|
|
37
|
+
"./package.json": "./package.json"
|
|
38
|
+
},
|
|
39
|
+
"files": [
|
|
40
|
+
"dist/**/*",
|
|
41
|
+
"README.md",
|
|
42
|
+
"SPEC.md",
|
|
43
|
+
"docs/**/*",
|
|
44
|
+
".env.defaults"
|
|
45
|
+
],
|
|
46
|
+
"scripts": {
|
|
47
|
+
"test:lint": "tsc --noEmit",
|
|
48
|
+
"test:unit": "node --conditions=plurnk-dev --env-file-if-exists=../plurnk-execs/.env.defaults --test \"src/**/*.test.ts\"",
|
|
49
|
+
"test": "npm run test:lint && npm run test:unit",
|
|
50
|
+
"build:clean": "rm -rf dist",
|
|
51
|
+
"build:dist": "tsc -p tsconfig.build.json",
|
|
52
|
+
"build": "npm run build:clean && npm run build:dist",
|
|
53
|
+
"prepack": "npm run build",
|
|
54
|
+
"prepublishOnly": "npm audit --audit-level=moderate && npm test"
|
|
55
|
+
},
|
|
56
|
+
"dependencies": {
|
|
57
|
+
"@modelcontextprotocol/client": "2.0.0"
|
|
58
|
+
},
|
|
59
|
+
"devDependencies": {
|
|
60
|
+
"@modelcontextprotocol/server": "2.0.0"
|
|
61
|
+
},
|
|
62
|
+
"peerDependencies": {
|
|
63
|
+
"@plurnk/plurnk-execs": "^1.4.0",
|
|
64
|
+
"@plurnk/plurnk-schemes": "^1.4.0"
|
|
65
|
+
}
|
|
66
|
+
}
|