@skillit/target-fastmcp 0.3.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024-present Pradeep Mouli
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,117 @@
1
+ # @skillit/target-fastmcp
2
+
3
+ > CLI-as-proxy invocation-target adapter for `@skillit/mcp`. Emits shell-command skills that use the [fastmcp](https://gofastmcp.com) Python CLI to invoke MCP tools.
4
+
5
+ Pairs with [`@skillit/mcp`](../mcp/). Where `@skillit/target-mcp-protocol` emits `mcp:` frontmatter for harnesses that hold an MCP session natively, `@skillit/target-fastmcp` emits a SKILL.md whose body is a series of shell commands the agent runs through its standard shell tool. The CLI terminates the MCP protocol at the shell boundary; the agent never sees MCP.
6
+
7
+ Target CLI: **`fastmcp@^2`** (Python, installed via `pip install fastmcp`).
8
+
9
+ ---
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ npm install --save-dev @skillit/target-fastmcp
15
+ ```
16
+
17
+ The adapter is loaded by `@skillit/mcp` on demand when you pass `--invocation cli:fastmcp`. Consumers of the rendered SKILL.md additionally need a Python environment with `fastmcp` installed — see Setup commands below.
18
+
19
+ ---
20
+
21
+ ## When to pick this target
22
+
23
+ Pick `cli:fastmcp` when **the agent harness has a shell tool but cannot speak MCP natively**, AND you prefer the Python `fastmcp` CLI to Node-based alternatives. Common reasons:
24
+
25
+ - Your team already deploys Python; another Node CLI would be the only Node dep.
26
+ - You want to use fastmcp's richer Python-side ergonomics (server authoring, debugging) end-to-end.
27
+ - The harness machine has Python pre-installed but not Node.
28
+
29
+ If neither of those applies, `cli:mcpc` is the lighter alternative — see [`@skillit/target-mcpc`](../target-mcpc/).
30
+
31
+ ---
32
+
33
+ ## What it emits
34
+
35
+ A `SKILL.md` body whose Tools section pairs each MCP tool with its concrete shell invocation:
36
+
37
+ ````markdown
38
+ ## search
39
+
40
+ Search the index.
41
+
42
+ ```sh
43
+ pyfastmcp call my-server search query=<value>
44
+ ```
45
+
46
+ ### Parameters
47
+
48
+ | MCP Name | CLI Flag/Key | Type | Required | Description |
49
+ | -------- | ------------- | ------ | -------- | ------------ |
50
+ | query | query=<value> | string | yes | Query string |
51
+ ````
52
+
53
+ Plus a Setup section with one-time install + connection registration commands, and a `generated-by:` frontmatter block carrying the adapter fingerprint.
54
+
55
+ ---
56
+
57
+ ## Argument encoding
58
+
59
+ The fastmcp CLI parses each positional after `call <server> <tool>` as `key=value`. Unlike mcpc, fastmcp does not currently expose a typed-literal form (`:=`) — every value is passed as a string and the server-side schema validator coerces. The adapter:
60
+
61
+ - Emits `key=<value>` for every parameter (Tier 1).
62
+ - Falls back to a single `--input-json '<JSON-payload>'` flag when any parameter is a complex object or array that wouldn't survive shell tokenization (Tier 3).
63
+
64
+ The Parameters table in the rendered Markdown shows the literal CLI form so the consumer can copy-paste with confidence.
65
+
66
+ ---
67
+
68
+ ## Setup commands
69
+
70
+ The Setup section the adapter emits looks like this (verbatim):
71
+
72
+ ```sh
73
+ # 1. Install fastmcp (Python CLI for invoking MCP servers; tested with fastmcp 2.x)
74
+ pip install fastmcp
75
+
76
+ # 2. Register this server (the renderer emits `pyfastmcp connect`, fastmcp's
77
+ # Python CLI binary name; some distributions alias it to `fastmcp`)
78
+ pyfastmcp connect <skill-name> -- <launchCommand>
79
+
80
+ # 3. (Optional) Verify the registration
81
+ pyfastmcp list
82
+ ```
83
+
84
+ ---
85
+
86
+ ## Adapter contract
87
+
88
+ | Field | Value |
89
+ | ---------------------------- | --------------------------------------------- |
90
+ | `target` | `'cli:fastmcp'` |
91
+ | `fingerprint.adapter` | `'@skillit/target-fastmcp'` |
92
+ | `fingerprint.version` | This package's `version` from `package.json`. |
93
+ | `fingerprint.targetCliRange` | `'fastmcp@^2'` |
94
+
95
+ Future major versions of fastmcp that change the `call` arg shape MUST bump this adapter's major version and update `targetCliRange` so the freshness audit (M5) can detect drift.
96
+
97
+ ---
98
+
99
+ ## Programmatic use
100
+
101
+ ```ts
102
+ import FastMcpAdapter from '@skillit/target-fastmcp';
103
+ import { renderSkill } from '@skillit/core';
104
+
105
+ const rendered = await renderSkill(skill, { invocation: FastMcpAdapter });
106
+ ```
107
+
108
+ ---
109
+
110
+ ## Further reading
111
+
112
+ - [`@skillit/mcp` README](../mcp/README.md) — host package, CLI usage.
113
+ - [`docs/adapter-authoring.md`](../mcp/docs/adapter-authoring.md) — building your own invocation adapter.
114
+
115
+ ## License
116
+
117
+ MIT
package/dist/args.d.ts ADDED
@@ -0,0 +1,61 @@
1
+ /**
2
+ * fastmcp argument encoder — converts classifier output into fastmcp CLI argv shape.
3
+ *
4
+ * @remarks
5
+ * fastmcp (the Python `fastmcp` / `pyfastmcp call` CLI,
6
+ * https://gofastmcp.com) accepts tool arguments in a single uniform form:
7
+ *
8
+ * - `key=value` — fastmcp parses the right-hand side based on the tool's
9
+ * declared schema, so we do NOT use a typed `key:=value` variant the way
10
+ * mcpc does. Numbers, booleans, enums, and string-arrays all share the
11
+ * same `key=<placeholder>` shape; the placeholder text describes the
12
+ * accepted value(s) for human readers.
13
+ *
14
+ * For Tier 3 fallback (anything we couldn't safely flatten), we emit a
15
+ * single `--input-json '<JSON-payload>'` argument. fastmcp's structured-input
16
+ * convention for passing whole-object payloads is the `--input-json` flag.
17
+ * The payload is a placeholder — this encoder is for documentation
18
+ * rendering, not runtime invocation, so actual values are substituted by
19
+ * the consumer at call time.
20
+ *
21
+ * @module args
22
+ */
23
+ import type { ParameterPlan } from '@skillit/mcp';
24
+ /** Encoder result — separated into normal flags vs Tier 3 fallback. */
25
+ export interface EncodedArgs {
26
+ /**
27
+ * Encoded arguments for Tier 1 + Tier 2 plans, one string per CLI token.
28
+ * Order matches insertion order of the input plan map (which itself
29
+ * preserves classifier walk order).
30
+ */
31
+ tier12: string[];
32
+ /**
33
+ * When ANY plan in the input has `tier === 3`, this is the single
34
+ * `--input-json '<JSON-payload>'` token string. Otherwise `null`. fastmcp
35
+ * accepts one `--input-json` per call carrying the structural arguments
36
+ * that couldn't be flattened into typed flags.
37
+ */
38
+ tier3Fallback: string | null;
39
+ }
40
+ /**
41
+ * Encode a classifier plan map as fastmcp argv tokens (documentation form).
42
+ *
43
+ * Encoding rules per tier:
44
+ *
45
+ * - Tier 1 + `type === 'scalar'` + scalarType `string` → `<path>=<value>`.
46
+ * - Tier 1 + `type === 'scalar'` + scalarType `number`/`integer` → `<path>=<value>`.
47
+ * - Tier 1 + `type === 'scalar'` + scalarType `boolean` → `<path>=<true|false>`.
48
+ * - Tier 1 + `type === 'enum'` → `<path>=<one-of-...>`.
49
+ * - Tier 1 + `type === 'string-array'` → `<path>=<comma-separated>`
50
+ * (fastmcp accepts CSV for repeatable string args).
51
+ * - Tier 2 → same as the leaf's Tier 1 form, with `<path>` joined by `.`.
52
+ * - Tier 3 → contributes nothing to `tier12`; sets `tier3Fallback`.
53
+ *
54
+ * Path is always joined with `.` (matches mcpc convention; fastmcp resolves
55
+ * dotted keys against nested schema properties).
56
+ *
57
+ * @param plan - classifier output (`Map<string, ParameterPlan>`)
58
+ * @returns split encoding result — Tier 1/2 tokens + optional Tier 3 fallback string
59
+ */
60
+ export declare function encodeFastMcpArgs(plan: Map<string, ParameterPlan>): EncodedArgs;
61
+ //# sourceMappingURL=args.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,uEAAuE;AACvE,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB;;;;;OAKG;IACH,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,GAAG,WAAW,CAiB/E"}
package/dist/args.js ADDED
@@ -0,0 +1,85 @@
1
+ /**
2
+ * fastmcp argument encoder — converts classifier output into fastmcp CLI argv shape.
3
+ *
4
+ * @remarks
5
+ * fastmcp (the Python `fastmcp` / `pyfastmcp call` CLI,
6
+ * https://gofastmcp.com) accepts tool arguments in a single uniform form:
7
+ *
8
+ * - `key=value` — fastmcp parses the right-hand side based on the tool's
9
+ * declared schema, so we do NOT use a typed `key:=value` variant the way
10
+ * mcpc does. Numbers, booleans, enums, and string-arrays all share the
11
+ * same `key=<placeholder>` shape; the placeholder text describes the
12
+ * accepted value(s) for human readers.
13
+ *
14
+ * For Tier 3 fallback (anything we couldn't safely flatten), we emit a
15
+ * single `--input-json '<JSON-payload>'` argument. fastmcp's structured-input
16
+ * convention for passing whole-object payloads is the `--input-json` flag.
17
+ * The payload is a placeholder — this encoder is for documentation
18
+ * rendering, not runtime invocation, so actual values are substituted by
19
+ * the consumer at call time.
20
+ *
21
+ * @module args
22
+ */
23
+ /**
24
+ * Encode a classifier plan map as fastmcp argv tokens (documentation form).
25
+ *
26
+ * Encoding rules per tier:
27
+ *
28
+ * - Tier 1 + `type === 'scalar'` + scalarType `string` → `<path>=<value>`.
29
+ * - Tier 1 + `type === 'scalar'` + scalarType `number`/`integer` → `<path>=<value>`.
30
+ * - Tier 1 + `type === 'scalar'` + scalarType `boolean` → `<path>=<true|false>`.
31
+ * - Tier 1 + `type === 'enum'` → `<path>=<one-of-...>`.
32
+ * - Tier 1 + `type === 'string-array'` → `<path>=<comma-separated>`
33
+ * (fastmcp accepts CSV for repeatable string args).
34
+ * - Tier 2 → same as the leaf's Tier 1 form, with `<path>` joined by `.`.
35
+ * - Tier 3 → contributes nothing to `tier12`; sets `tier3Fallback`.
36
+ *
37
+ * Path is always joined with `.` (matches mcpc convention; fastmcp resolves
38
+ * dotted keys against nested schema properties).
39
+ *
40
+ * @param plan - classifier output (`Map<string, ParameterPlan>`)
41
+ * @returns split encoding result — Tier 1/2 tokens + optional Tier 3 fallback string
42
+ */
43
+ export function encodeFastMcpArgs(plan) {
44
+ const tier12 = [];
45
+ let hasTier3 = false;
46
+ for (const [, p] of plan) {
47
+ if (p.tier === 3) {
48
+ hasTier3 = true;
49
+ continue;
50
+ }
51
+ const key = p.path.join('.');
52
+ tier12.push(encodeOne(key, p));
53
+ }
54
+ return {
55
+ tier12,
56
+ tier3Fallback: hasTier3 ? `--input-json '<JSON-payload>'` : null
57
+ };
58
+ }
59
+ function encodeOne(key, plan) {
60
+ // Tier 1/2 leaves only — Tier 3 (`type: 'json'`) short-circuited in the
61
+ // caller. We still cover the `'json'` arm explicitly so `switch` is
62
+ // exhaustive and TS proves no arm is missed.
63
+ switch (plan.type) {
64
+ case 'scalar': {
65
+ if (plan.scalarType === 'boolean')
66
+ return `${key}=<true|false>`;
67
+ // string / number / integer — fastmcp parses by schema.
68
+ return `${key}=<value>`;
69
+ }
70
+ case 'enum':
71
+ // DU guarantees `plan.enum.length >= 1`.
72
+ return `${key}=<one-of-${plan.enum.join('|')}>`;
73
+ case 'string-array':
74
+ return `${key}=<comma-separated>`;
75
+ case 'json':
76
+ // Defensive: callers filter Tier 3 above. fastmcp accepts
77
+ // `key=<value>` as a JSON literal when the schema demands it.
78
+ return `${key}=<value>`;
79
+ default: {
80
+ const _exhaustive = plan;
81
+ throw new Error(`encodeOne: unhandled ParameterPlan arm: ${JSON.stringify(_exhaustive)}`);
82
+ }
83
+ }
84
+ }
85
+ //# sourceMappingURL=args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.js","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAqBH;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAgC;IAChE,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;QACzB,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACjB,QAAQ,GAAG,IAAI,CAAC;YAChB,SAAS;QACX,CAAC;QACD,MAAM,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC7B,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;IACjC,CAAC;IAED,OAAO;QACL,MAAM;QACN,aAAa,EAAE,QAAQ,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC,IAAI;KACjE,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,GAAW,EAAE,IAAmB;IACjD,wEAAwE;IACxE,oEAAoE;IACpE,6CAA6C;IAC7C,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS;gBAAE,OAAO,GAAG,GAAG,eAAe,CAAC;YAChE,wDAAwD;YACxD,OAAO,GAAG,GAAG,UAAU,CAAC;QAC1B,CAAC;QACD,KAAK,MAAM;YACT,yCAAyC;YACzC,OAAO,GAAG,GAAG,YAAY,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;QAClD,KAAK,cAAc;YACjB,OAAO,GAAG,GAAG,oBAAoB,CAAC;QACpC,KAAK,MAAM;YACT,0DAA0D;YAC1D,8DAA8D;YAC9D,OAAO,GAAG,GAAG,UAAU,CAAC;QAC1B,OAAO,CAAC,CAAC,CAAC;YACR,MAAM,WAAW,GAAU,IAAI,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,2CAA2C,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QAC5F,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * `@skillit/target-fastmcp` — CLI-as-proxy invocation-target adapter.
3
+ *
4
+ * Resolved by `@skillit/mcp`'s adapter loader when target `cli:fastmcp` is
5
+ * requested. Emits SKILL.md output that routes tool calls through the
6
+ * Python `fastmcp` CLI, making the skill consumable by any agent with a
7
+ * shell tool (rather than only MCP-native harnesses).
8
+ *
9
+ * @packageDocumentation
10
+ */
11
+ export { FastMcpAdapter } from './render.js';
12
+ export { encodeFastMcpArgs } from './args.js';
13
+ export type { EncodedArgs } from './args.js';
14
+ export { renderFastMcpSetup } from './setup.js';
15
+ export type { StdioLaunchCommand, HttpLaunchEndpoint } from './setup.js';
16
+ export { PACKAGE_VERSION } from './version.js';
17
+ import { FastMcpAdapter } from './render.js';
18
+ declare const adapter: FastMcpAdapter;
19
+ /**
20
+ * Default export — singleton adapter instance resolved by the adapter loader.
21
+ *
22
+ * @example
23
+ * ```ts
24
+ * import adapter from '@skillit/target-fastmcp';
25
+ * await adapter.render(skill, ctx);
26
+ * ```
27
+ */
28
+ export default adapter;
29
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,YAAY,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,QAAA,MAAM,OAAO,gBAAuB,CAAC;AAErC;;;;;;;;GAQG;AACH,eAAe,OAAO,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,27 @@
1
+ /**
2
+ * `@skillit/target-fastmcp` — CLI-as-proxy invocation-target adapter.
3
+ *
4
+ * Resolved by `@skillit/mcp`'s adapter loader when target `cli:fastmcp` is
5
+ * requested. Emits SKILL.md output that routes tool calls through the
6
+ * Python `fastmcp` CLI, making the skill consumable by any agent with a
7
+ * shell tool (rather than only MCP-native harnesses).
8
+ *
9
+ * @packageDocumentation
10
+ */
11
+ export { FastMcpAdapter } from './render.js';
12
+ export { encodeFastMcpArgs } from './args.js';
13
+ export { renderFastMcpSetup } from './setup.js';
14
+ export { PACKAGE_VERSION } from './version.js';
15
+ import { FastMcpAdapter } from './render.js';
16
+ const adapter = new FastMcpAdapter();
17
+ /**
18
+ * Default export — singleton adapter instance resolved by the adapter loader.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * import adapter from '@skillit/target-fastmcp';
23
+ * await adapter.render(skill, ctx);
24
+ * ```
25
+ */
26
+ export default adapter;
27
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAE9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEhD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,OAAO,GAAG,IAAI,cAAc,EAAE,CAAC;AAErC;;;;;;;;GAQG;AACH,eAAe,OAAO,CAAC"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * `FastMcpAdapter` — CLI-as-proxy invocation adapter for the Python `fastmcp` CLI.
3
+ *
4
+ * @remarks
5
+ * Emits SKILL.md output usable by any agent with a shell tool, by routing
6
+ * tool calls through `fastmcp` (https://gofastmcp.com). Unlike the
7
+ * `mcp-protocol` adapter, this adapter does NOT emit an `mcp:` frontmatter
8
+ * block — the MCP server connection is established via the shell
9
+ * `pyfastmcp connect` command described in the Setup section. Instead it
10
+ * emits a `generated-by:` block carrying the adapter's fingerprint
11
+ * (FR-IT-012).
12
+ *
13
+ * The body delegates to core's default render path with two extensions:
14
+ *
15
+ * 1. `bodyPrefix` — the Setup section is prepended to the SKILL.md body so
16
+ * the consumer sees install/connect instructions before the standard
17
+ * skill content.
18
+ * 2. `skipDefaultFunctionsRef` — the default `references/functions.md` is
19
+ * suppressed; the adapter emits its own `references/tools.md` carrying
20
+ * fastmcp command-shape rows produced by `renderCliParamTable`.
21
+ *
22
+ * Resources/prompts/types/etc. references are inherited from core
23
+ * unchanged — the only kind requiring CLI-specific rendering is functions
24
+ * (which become tools in the fastmcp dialect).
25
+ *
26
+ * @module render
27
+ */
28
+ import type { AdapterFingerprint, AdapterRenderContext, ExtractedSkill, RenderedSkill } from '@skillit/core';
29
+ import type { InvocationAdapter } from '@skillit/mcp';
30
+ /**
31
+ * fastmcp CLI-as-proxy adapter — emits shell-command skills consumable by
32
+ * any agent with a `bash`/`shell` tool.
33
+ *
34
+ * @public
35
+ */
36
+ export declare class FastMcpAdapter implements InvocationAdapter {
37
+ readonly target: "cli:fastmcp";
38
+ readonly fingerprint: AdapterFingerprint;
39
+ constructor();
40
+ /**
41
+ * Render an `ExtractedSkill` into a `RenderedSkill` carrying fastmcp
42
+ * command-shape SKILL.md output.
43
+ *
44
+ * The launch shape is selected by `resolveLaunchCommand` from `ctx.mode`.
45
+ */
46
+ render(skill: ExtractedSkill, ctx: AdapterRenderContext): Promise<RenderedSkill>;
47
+ }
48
+ //# sourceMappingURL=render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAClB,oBAAoB,EAEpB,cAAc,EAEd,aAAa,EACd,MAAM,eAAe,CAAC;AAEvB,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,cAAc,CAAC;AAOrE;;;;;GAKG;AACH,qBAAa,cAAe,YAAW,iBAAiB;IACtD,QAAQ,CAAC,MAAM,EAAG,aAAa,CAAU;IACzC,QAAQ,CAAC,WAAW,EAAE,kBAAkB,CAAC;;IAUzC;;;;;OAKG;IACG,MAAM,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,EAAE,oBAAoB,GAAG,OAAO,CAAC,aAAa,CAAC;CAmCvF"}
package/dist/render.js ADDED
@@ -0,0 +1,149 @@
1
+ /**
2
+ * `FastMcpAdapter` — CLI-as-proxy invocation adapter for the Python `fastmcp` CLI.
3
+ *
4
+ * @remarks
5
+ * Emits SKILL.md output usable by any agent with a shell tool, by routing
6
+ * tool calls through `fastmcp` (https://gofastmcp.com). Unlike the
7
+ * `mcp-protocol` adapter, this adapter does NOT emit an `mcp:` frontmatter
8
+ * block — the MCP server connection is established via the shell
9
+ * `pyfastmcp connect` command described in the Setup section. Instead it
10
+ * emits a `generated-by:` block carrying the adapter's fingerprint
11
+ * (FR-IT-012).
12
+ *
13
+ * The body delegates to core's default render path with two extensions:
14
+ *
15
+ * 1. `bodyPrefix` — the Setup section is prepended to the SKILL.md body so
16
+ * the consumer sees install/connect instructions before the standard
17
+ * skill content.
18
+ * 2. `skipDefaultFunctionsRef` — the default `references/functions.md` is
19
+ * suppressed; the adapter emits its own `references/tools.md` carrying
20
+ * fastmcp command-shape rows produced by `renderCliParamTable`.
21
+ *
22
+ * Resources/prompts/types/etc. references are inherited from core
23
+ * unchanged — the only kind requiring CLI-specific rendering is functions
24
+ * (which become tools in the fastmcp dialect).
25
+ *
26
+ * @module render
27
+ */
28
+ import { estimateTokens, renderSkill, truncateToTokenBudget } from '@skillit/core';
29
+ import { generatedByFrontmatter, splitToolsByNamespace } from '@skillit/mcp';
30
+ import { renderToolsBody, resolveLaunchCommand } from '@skillit/mcp/adapter-utils';
31
+ import { encodeFastMcpArgs } from './args.js';
32
+ import { renderFastMcpSetup } from './setup.js';
33
+ import { PACKAGE_VERSION } from './version.js';
34
+ /**
35
+ * fastmcp CLI-as-proxy adapter — emits shell-command skills consumable by
36
+ * any agent with a `bash`/`shell` tool.
37
+ *
38
+ * @public
39
+ */
40
+ export class FastMcpAdapter {
41
+ target = 'cli:fastmcp';
42
+ fingerprint;
43
+ constructor() {
44
+ this.fingerprint = {
45
+ adapter: '@skillit/target-fastmcp',
46
+ version: PACKAGE_VERSION,
47
+ targetCliRange: 'fastmcp@^2'
48
+ };
49
+ }
50
+ /**
51
+ * Render an `ExtractedSkill` into a `RenderedSkill` carrying fastmcp
52
+ * command-shape SKILL.md output.
53
+ *
54
+ * The launch shape is selected by `resolveLaunchCommand` from `ctx.mode`.
55
+ */
56
+ async render(skill, ctx) {
57
+ const launchCommand = resolveLaunchCommand(ctx);
58
+ // Frontmatter — `generated-by:` only. Do NOT emit `mcp:` block.
59
+ const additionalFrontmatter = generatedByFrontmatter(this.fingerprint);
60
+ // Setup section — install + connect commands + FR-IT-012 trace line.
61
+ const bodyPrefix = renderFastMcpSetup(ctx.skillName, launchCommand, this.fingerprint);
62
+ // Delegate body to core's default path. We disable:
63
+ // - the default functions.md emission (we emit our own tools.md below)
64
+ // - the inner canonicalize pass — because we mutate `references` after
65
+ // this call, and a single canonicalize run at the host's outer wrapper
66
+ // is sufficient (and avoids a redundant second pass on the body).
67
+ const baseRendered = renderSkill(skill, {
68
+ maxTokens: ctx.maxTokens,
69
+ additionalFrontmatter,
70
+ bodyPrefix,
71
+ skipDefaultFunctionsRef: true,
72
+ canonicalize: false,
73
+ invocation: undefined,
74
+ namePrefix: ctx.skillName
75
+ });
76
+ // Append our own tools.md (or per-namespace tools-<ns>.md split) if
77
+ // there are any tools. The host's outer canonicalize wrapper (in
78
+ // renderSkill's invocation-adapter dispatch) runs exactly once over
79
+ // this final shape, including the tools file(s).
80
+ const toolsRefs = renderToolsReference(skill.functions, ctx.skillName, ctx.maxTokens);
81
+ for (const ref of toolsRefs) {
82
+ baseRendered.references.push(ref);
83
+ }
84
+ return baseRendered;
85
+ }
86
+ }
87
+ /**
88
+ * Build the `references/tools.md` file(s) with fastmcp command-shape rows.
89
+ *
90
+ * Returns an empty array when the IR has no tools (so the adapter doesn't
91
+ * emit an empty file). When the rendered body fits inside `maxTokens`, a
92
+ * single `references/tools.md` is returned. Otherwise the helper splits
93
+ * the surface by first-segment namespace (FR-022) and returns one
94
+ * `references/tools-<ns>.md` per namespace. Each emitted file has its
95
+ * content passed through `truncateToTokenBudget` so even a single
96
+ * oversized namespace cannot blow past the budget; the `tokens` field
97
+ * reports the pre-truncation estimate, matching the convention used by
98
+ * core's renderer.
99
+ */
100
+ function renderToolsReference(functions, skillName, maxTokens) {
101
+ if (functions.length === 0)
102
+ return [];
103
+ const cliVerb = `pyfastmcp call ${skillName}`;
104
+ const groups = splitToolsByNamespace(functions, (subset) => estimateTokens(renderToolsBody(subset, skillName, encodePlanForTable, encodeFastMcpArgs, cliVerb)), maxTokens);
105
+ const files = [];
106
+ for (const group of groups) {
107
+ const content = renderToolsBody(group.tools, skillName, encodePlanForTable, encodeFastMcpArgs, cliVerb);
108
+ const filename = group.name === 'tools'
109
+ ? `${skillName}/references/tools.md`
110
+ : `${skillName}/references/tools-${group.name}.md`;
111
+ files.push({
112
+ filename,
113
+ content: truncateToTokenBudget(content, maxTokens),
114
+ tokens: estimateTokens(content)
115
+ });
116
+ }
117
+ return files;
118
+ }
119
+ /**
120
+ * Encoder used by `renderCliParamTable`. Identical encoding rules to
121
+ * `encodeFastMcpArgs` but operates on a single plan so it can be the
122
+ * per-row-callback the table expects.
123
+ *
124
+ * fastmcp-specific: all flags use `=` (fastmcp parses RHS by schema), and
125
+ * Tier 3 fallback emits `--input-json '<JSON-payload>'`.
126
+ */
127
+ function encodePlanForTable(plan) {
128
+ const key = plan.path.join('.');
129
+ switch (plan.type) {
130
+ case 'json':
131
+ return `--input-json '<JSON-payload>'`;
132
+ case 'scalar': {
133
+ if (plan.scalarType === 'boolean')
134
+ return `${key}=<true|false>`;
135
+ // string / number / integer
136
+ return `${key}=<value>`;
137
+ }
138
+ case 'enum':
139
+ // DU guarantees `plan.enum.length >= 1`.
140
+ return `${key}=<one-of-${plan.enum.join('|')}>`;
141
+ case 'string-array':
142
+ return `${key}=<comma-separated>`;
143
+ default: {
144
+ const _exhaustive = plan;
145
+ throw new Error(`encodePlanForTable: unhandled ParameterPlan arm: ${JSON.stringify(_exhaustive)}`);
146
+ }
147
+ }
148
+ }
149
+ //# sourceMappingURL=render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Setup-section renderer for the fastmcp CLI-as-proxy adapter.
3
+ *
4
+ * @remarks
5
+ * fastmcp (the Python `fastmcp` / `pyfastmcp` CLI, https://gofastmcp.com)
6
+ * lets non-MCP agents talk to MCP servers via shell commands. The Setup
7
+ * section embedded into SKILL.md tells the consumer:
8
+ *
9
+ * 1. How to install fastmcp (`pip install fastmcp`).
10
+ * 2. How to register the underlying MCP server (`pyfastmcp connect <name> -- ...`)
11
+ * using the launch command we received from the host.
12
+ * 3. The adapter fingerprint (FR-IT-012) — a human-readable line so
13
+ * freshness audits can detect drift between the rendered SKILL.md and
14
+ * the adapter version that produced it.
15
+ *
16
+ * @module setup
17
+ */
18
+ import type { AdapterFingerprint } from '@skillit/mcp';
19
+ /**
20
+ * Stdio launch shape — mirrors the host's `AdapterRenderContext.launchCommand`.
21
+ */
22
+ export interface StdioLaunchCommand {
23
+ readonly command: string;
24
+ readonly args?: readonly string[];
25
+ readonly env?: Readonly<Record<string, string>>;
26
+ }
27
+ /**
28
+ * HTTP endpoint shape — mirrors the host's `AdapterRenderContext.httpEndpoint`.
29
+ */
30
+ export interface HttpLaunchEndpoint {
31
+ readonly url: string;
32
+ readonly headers?: Readonly<Record<string, string>>;
33
+ }
34
+ /**
35
+ * Render the Markdown Setup section for a fastmcp-proxied skill.
36
+ *
37
+ * @param skillName - kebab-case skill identifier; used as the fastmcp connection name
38
+ * @param launchCommand - stdio command (`{ command, args?, env? }`) or HTTP endpoint (`{ url, headers? }`)
39
+ * @param fingerprint - adapter fingerprint embedded in the FR-IT-012 trace line
40
+ * @returns Markdown string starting with `## Setup` and ending with the trace line
41
+ */
42
+ export declare function renderFastMcpSetup(skillName: string, launchCommand: StdioLaunchCommand | HttpLaunchEndpoint, fingerprint: AdapterFingerprint): string;
43
+ //# sourceMappingURL=setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEvD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACjD;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACrD;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,kBAAkB,GAAG,kBAAkB,EACtD,WAAW,EAAE,kBAAkB,GAC9B,MAAM,CA0BR"}
package/dist/setup.js ADDED
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Setup-section renderer for the fastmcp CLI-as-proxy adapter.
3
+ *
4
+ * @remarks
5
+ * fastmcp (the Python `fastmcp` / `pyfastmcp` CLI, https://gofastmcp.com)
6
+ * lets non-MCP agents talk to MCP servers via shell commands. The Setup
7
+ * section embedded into SKILL.md tells the consumer:
8
+ *
9
+ * 1. How to install fastmcp (`pip install fastmcp`).
10
+ * 2. How to register the underlying MCP server (`pyfastmcp connect <name> -- ...`)
11
+ * using the launch command we received from the host.
12
+ * 3. The adapter fingerprint (FR-IT-012) — a human-readable line so
13
+ * freshness audits can detect drift between the rendered SKILL.md and
14
+ * the adapter version that produced it.
15
+ *
16
+ * @module setup
17
+ */
18
+ /**
19
+ * Render the Markdown Setup section for a fastmcp-proxied skill.
20
+ *
21
+ * @param skillName - kebab-case skill identifier; used as the fastmcp connection name
22
+ * @param launchCommand - stdio command (`{ command, args?, env? }`) or HTTP endpoint (`{ url, headers? }`)
23
+ * @param fingerprint - adapter fingerprint embedded in the FR-IT-012 trace line
24
+ * @returns Markdown string starting with `## Setup` and ending with the trace line
25
+ */
26
+ export function renderFastMcpSetup(skillName, launchCommand, fingerprint) {
27
+ const lines = [];
28
+ lines.push('## Setup');
29
+ lines.push('');
30
+ lines.push('This skill proxies through `fastmcp`, the Python MCP CLI.');
31
+ lines.push('');
32
+ lines.push('### One-time install');
33
+ lines.push('');
34
+ lines.push('```sh');
35
+ lines.push('pip install fastmcp');
36
+ lines.push('```');
37
+ lines.push('');
38
+ lines.push(`### Connect to ${skillName}`);
39
+ lines.push('');
40
+ lines.push('```sh');
41
+ lines.push(renderConnectCommand(skillName, launchCommand));
42
+ lines.push('```');
43
+ lines.push('');
44
+ // FR-IT-012 trace line. The "fastmcp 2.x" marker corresponds to this
45
+ // adapter's `targetCliRange` (fastmcp@^2) — keep them in sync. The
46
+ // `via @skillit/target-fastmcp <version>` suffix matches the spec wording.
47
+ const cliMarker = formatCliMarker(fingerprint.targetCliRange);
48
+ lines.push(`> Generated for ${cliMarker} via ${fingerprint.adapter} ${fingerprint.version}`);
49
+ return lines.join('\n');
50
+ }
51
+ function renderConnectCommand(skillName, launchCommand) {
52
+ if ('url' in launchCommand) {
53
+ return `pyfastmcp connect ${shellQuote(skillName)} --url ${shellQuote(launchCommand.url)}`;
54
+ }
55
+ const argv = launchCommand.args && launchCommand.args.length > 0
56
+ ? ` ${launchCommand.args.map(shellQuote).join(' ')}`
57
+ : '';
58
+ return `pyfastmcp connect ${shellQuote(skillName)} -- ${shellQuote(launchCommand.command)}${argv}`;
59
+ }
60
+ /**
61
+ * Minimal POSIX shell quoting for tokens emitted into a copy/paste-ready
62
+ * Setup command. See target-mcpc's `setup.ts` for full rationale; the
63
+ * heuristic is identical (`safe charset` passthrough, single-quote with
64
+ * `'\''` escape otherwise).
65
+ */
66
+ function shellQuote(token) {
67
+ if (token.length > 0 && /^[A-Za-z0-9_./@:=+-]+$/.test(token))
68
+ return token;
69
+ return `'${token.replace(/'/g, `'\\''`)}'`;
70
+ }
71
+ /**
72
+ * Format the targetCliRange (e.g. `fastmcp@^2`) into the marker form used in
73
+ * the human-readable fingerprint line ("fastmcp 2.x"). Falls back to a
74
+ * conservative "fastmcp" if the range is missing or unparseable so the
75
+ * fingerprint line remains stable.
76
+ */
77
+ function formatCliMarker(targetCliRange) {
78
+ if (!targetCliRange)
79
+ return 'fastmcp';
80
+ // Match `<name>@<range>` where range starts with ^/~/= followed by a
81
+ // major version (with optional minor). Render as either "<name>
82
+ // <major>.<minor>.x" when both are present or "<name> <major>.x" when
83
+ // only major is provided.
84
+ const fullMatch = targetCliRange.match(/^([^@]+)@[\^~=]?(\d+)\.(\d+)/);
85
+ if (fullMatch) {
86
+ const [, name, major, minor] = fullMatch;
87
+ return `${name} ${major}.${minor}.x`;
88
+ }
89
+ const majorMatch = targetCliRange.match(/^([^@]+)@[\^~=]?(\d+)/);
90
+ if (majorMatch) {
91
+ const [, name, major] = majorMatch;
92
+ return `${name} ${major}.x`;
93
+ }
94
+ // Operators outside [\^~=] (e.g. `>=`, `<`) — strip the @range suffix and
95
+ // return just the package name so the fingerprint line stays human-readable.
96
+ // The fingerprint frontmatter still carries the precise raw range.
97
+ const nameOnly = targetCliRange.match(/^([^@]+)@/);
98
+ if (nameOnly)
99
+ return nameOnly[1];
100
+ return targetCliRange;
101
+ }
102
+ //# sourceMappingURL=setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Adapter package version — embedded into the `AdapterFingerprint`.
3
+ *
4
+ * @remarks
5
+ * Kept in a separate module so `render.ts` doesn't need to import the
6
+ * default export of `index.ts` (which would create a small circular import).
7
+ * Bump this string whenever the adapter's output shape changes.
8
+ */
9
+ export declare const PACKAGE_VERSION = "0.1.0";
10
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,UAAU,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Adapter package version — embedded into the `AdapterFingerprint`.
3
+ *
4
+ * @remarks
5
+ * Kept in a separate module so `render.ts` doesn't need to import the
6
+ * default export of `index.ts` (which would create a small circular import).
7
+ * Bump this string whenever the adapter's output shape changes.
8
+ */
9
+ export const PACKAGE_VERSION = '0.1.0';
10
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC"}
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@skillit/target-fastmcp",
3
+ "version": "0.3.0",
4
+ "description": "FastMCP CLI-as-proxy invocation-target adapter for @skillit/mcp — emits shell-command skills using the fastmcp Python CLI for agents without MCP support",
5
+ "keywords": [
6
+ "agent-skills",
7
+ "ai",
8
+ "fastmcp",
9
+ "mcp",
10
+ "model-context-protocol",
11
+ "skillit"
12
+ ],
13
+ "license": "MIT",
14
+ "author": "Pradeep Mouli",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/pradeepmouli/skillit.git",
18
+ "directory": "packages/target-fastmcp"
19
+ },
20
+ "funding": {
21
+ "type": "github",
22
+ "url": "https://github.com/sponsors/pradeepmouli"
23
+ },
24
+ "files": [
25
+ "dist",
26
+ "README.md"
27
+ ],
28
+ "type": "module",
29
+ "main": "./dist/index.js",
30
+ "types": "./dist/index.d.ts",
31
+ "exports": {
32
+ ".": {
33
+ "types": "./dist/index.d.ts",
34
+ "import": "./dist/index.js"
35
+ }
36
+ },
37
+ "dependencies": {
38
+ "@skillit/core": "1.5.0",
39
+ "@skillit/mcp": "0.3.0"
40
+ },
41
+ "devDependencies": {
42
+ "@types/json-schema": "^7.0.15",
43
+ "@types/node": "^25.9.1",
44
+ "vitest": "^4.1.7",
45
+ "yaml": "^2.9.0"
46
+ },
47
+ "scripts": {
48
+ "build": "tsc -p tsconfig.build.json",
49
+ "type-check": "tsc --noEmit",
50
+ "test": "vitest run"
51
+ }
52
+ }