@modootoday/pmcp 0.4.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -53,15 +53,48 @@ Run `pmcp --help` or `pmcp <command> --help` for options. With no command,
53
53
  `pmcp` serves MCP on stdio. Use `--root <node_modules>` to select a local tree
54
54
  and repeat `--scope <prefix>` to restrict local package discovery.
55
55
 
56
+ ## Project config
57
+
58
+ A `pmcp.toml` at or above the working directory sets the catalog once, so a
59
+ host entry needs no flags and works from any package in the repository:
60
+
61
+ ```toml
62
+ [catalog]
63
+ workspaces = [".", "packages/*"]
64
+ packages = ["docs"]
65
+ marketplaces = ["vendor/marketplace"]
66
+ ```
67
+
68
+ Paths resolve against the file's directory. Keys are `roots`, `scopes`,
69
+ `workspaces`, `packages` and `marketplaces`, each a list mirroring the flag of
70
+ the same meaning; an unknown key is an error. A flag replaces the file's list
71
+ of its kind. `--config <file>` names another file and `--no-config` ignores it.
72
+
56
73
  ## Package skills
57
74
 
58
- Skills are discovered by filename, including `skills/`, `.agent/skills/`,
59
- `.claude/skills/`, `.gemini/skills/`, `.codex/skills/`, and `lib/skill/` layouts
75
+ Skills are discovered by filename, including `skills/`, `.agents/skills/`,
76
+ `.agent/skills/`, `.claude/skills/`, `.gemini/skills/`, `.codex/skills/`, and
77
+ `lib/skill/` layouts
60
78
  within the discovery depth. A skill needs a frontmatter `description` for search.
61
79
 
62
80
  `skill_find` accepts a problem description and returns matching skills.
63
81
  `skill_call` opens the selected document. Local MCP reading requires no login.
64
82
 
83
+ Marketplace plugins also carry commands, agents, hooks and MCP servers.
84
+ Commands are listed as skills. The others are listed under their own kind and
85
+ are left out of `skill_catalog` and `skill_find` unless `kind` asks for them
86
+ (`agent`, `hook`, `mcp`, or `any`); `skill_describe`, `skill_read` and
87
+ `skill_call` work on every kind.
88
+
89
+ ## MCP Skills extension
90
+
91
+ The server also declares `io.modelcontextprotocol/skills` (SEP-2640): it
92
+ answers `skills/list` and `skills/get`, and serves each file of a conforming
93
+ skill as `skill://pmcp/<package>/<name>/<file>` through `resources/read`, with
94
+ a sha256 digest and size per file. A skill qualifies when its frontmatter
95
+ `name` matches its directory and the Agent Skills naming rules, and it stays
96
+ within 512 files and 16 MiB; the rest remain reachable through the tools.
97
+
65
98
  ## Hosting over HTTP
66
99
 
67
100
  `@modootoday/pmcp/http` serves the same five tools over streamable HTTP for a hosted catalog.
@@ -76,7 +109,8 @@ import { createSkillHttpHandler } from "@modootoday/pmcp/http";
76
109
  const skills = createSkillHttpHandler({
77
110
  roots: [],
78
111
  marketplaces: ["/srv/marketplace", "/srv/marketplace-free"],
79
- authorize: async (request) => verifyBearer(request.headers.get("authorization")),
112
+ authorize: async (request) =>
113
+ verifyBearer(request.headers.get("authorization")),
80
114
  });
81
115
  export default { fetch: (request: Request) => skills.fetch(request) };
82
116
  ```
@@ -20,7 +20,18 @@ interface SkillEntry {
20
20
  readonly metadata?: Readonly<Record<string, string | readonly string[]>>;
21
21
  /** Extra search terms. Ranked with the description, never used as triggers. */
22
22
  readonly keywords?: readonly string[];
23
+ /** What the entry is. Absent means a skill. */
24
+ readonly kind?: AssetKind;
25
+ /**
26
+ * What describe and read may open: a directory, or one file for an asset
27
+ * that is a single file. Absent means the directory holding `path`.
28
+ */
29
+ readonly root?: string;
23
30
  }
31
+ /** Everything the catalog serves. Commands are skills; workflows have no kind of their own. */
32
+ declare const ASSET_KINDS: readonly ["skill", "agent", "hook", "mcp"];
33
+ type AssetKind = (typeof ASSET_KINDS)[number];
34
+ declare const kindOf: (entry: Pick<SkillEntry, "kind">) => AssetKind;
24
35
  interface CatalogOptions {
25
36
  /** Directories to walk. Each is a `node_modules` root, not a package root. */
26
37
  readonly roots: readonly string[];
@@ -83,4 +94,4 @@ declare function withoutBody({ path, ...rest }: SkillEntry): Omit<SkillEntry, "p
83
94
  /** Path relative to a root, for a message a reader can act on. */
84
95
  declare function displayPath(root: string, entry: SkillEntry): string;
85
96
 
86
- export { type CatalogOptions as C, MAX_SKILL_DEPTH as M, type SkillEntry as S, SKIPPED_DIRS as a, readCatalog as b, readFrontmatter as c, displayPath as d, readBody as r, withoutBody as w };
97
+ export { type AssetKind as A, type CatalogOptions as C, MAX_SKILL_DEPTH as M, type SkillEntry as S, ASSET_KINDS as a, SKIPPED_DIRS as b, readCatalog as c, displayPath as d, readFrontmatter as e, kindOf as k, readBody as r, withoutBody as w };