@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 +21 -0
- package/README.md +117 -0
- package/dist/args.d.ts +61 -0
- package/dist/args.d.ts.map +1 -0
- package/dist/args.js +85 -0
- package/dist/args.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/render.d.ts +48 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +149 -0
- package/dist/render.js.map +1 -0
- package/dist/setup.d.ts +43 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +102 -0
- package/dist/setup.js.map +1 -0
- package/dist/version.d.ts +10 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +10 -0
- package/dist/version.js.map +1 -0
- package/package.json +52 -0
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
|
package/dist/args.js.map
ADDED
|
@@ -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"}
|
package/dist/index.d.ts
ADDED
|
@@ -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"}
|
package/dist/render.d.ts
ADDED
|
@@ -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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"}
|
package/dist/setup.d.ts
ADDED
|
@@ -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"}
|
package/dist/version.js
ADDED
|
@@ -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
|
+
}
|