Skip to main content
Glama
olaservo

skills-over-mcp-demo

by olaservo

skills-over-mcp-demo

Demo MCP server that serves Agent Skills over MCP per SEP-2640 v1 (Skills Extension), built on the v2 TypeScript SDK (@modelcontextprotocol/server) and the experimental skills extension SDK (@olaservo/ext-skills).

Quickstart

npm install
npm run smoke       # build + end-to-end client checks over stdio
npm run smoke:http  # same checks over streamable HTTP (the transport OpenAI's importer uses)

Both smoke tests connect with versionNegotiation: { mode: "auto" } and assert the connection lands on the latest protocol revision (2026-07-28) and that skills/list carries the SEP-2549 caching attributes, which the SEP scopes to that revision.

Or run the server directly for use from a host:

npm run build
node dist/index.js                    # stdio, serves the bundled skills/ directory
node dist/index.js path/to/dir        # stdio, different skills directory
node dist/http.js --port 3000        # streamable HTTP at http://127.0.0.1:3000/mcp

Claude Desktop / generic stdio host config:

{
  "mcpServers": {
    "skills-over-mcp-demo": {
      "command": "node",
      "args": ["<absolute path>/dist/index.js"]
    }
  }
}

Related MCP server: skill4agent MCP Server

What it demonstrates

SEP-2640 surface

Where

Capability declaration capabilities.extensions["io.modelcontextprotocol/skills"]

registerSkillResources() declares it before connect

skills/list — entries with verbatim frontmatter + complete {uri, digest} manifest

3 listed skills

skills/get — entry retrieval by URI, listed or not; -32602 for non-skills

the unlisted secret-menu skill

Partial listings + server instructions as a skill pointer

secret-menu is served but never enumerated; instructions point to it

resources/read — every skill file individually addressable

skill://… resources + catch-all template

resources/directory/read (optional, gated on directoryRead)

declared and implemented

SEP-2549 list-caching attributes on skills/list (2026-07-28+)

ttlMs: 60_000, cacheScope: "public"

Multi-segment skill paths

skill://dice-roller/tabletop-dice/SKILL.md

Opt-in tools bridge (--tools-bridge)

list_skills + read_skill (read-only, annotations.readOnlyHint)

Interop finding: ChatGPT connector creation fails against a tools-less MCP server — the "New Plugin" dialog errors out generically when tools/list returns -32601, even though the server is a valid SEP-2640 skills/resources server. The --tools-bridge flag exists for that case. It is off by default and not part of SEP-2640: the SEP defines no server-side tools (its reader-tool guidance is for host-provided tools), so the default surface stays pure-SEP. The flag mirrors that host-side reader tool server-side so tool-only hosts can consume the skills at all; the HF Space deployment enables it.

Skills served:

skill://dice-roller/tabletop-dice/SKILL.md    multi-segment path, references/ supporting file
skill://mcp-glossary/SKILL.md                 single-file skill
skill://release-notes-writer/SKILL.md         templates/ supporting file
skill://secret-menu/SKILL.md                  UNLISTED — reachable via skills/get + instructions pointer only

The smoke test (src/smoke.ts) exercises the client side of the SEP: capability gating, enumeration, unlisted-skill retrieval, digest + frontmatter verification on reads, unlisted-file rejection semantics, directory walking, and discoverAndBuildCatalog() producing a system-prompt catalog that merges the instructions-pointer skill with the listing.

Public endpoint (Hugging Face Space)

The server is deployed as a public Docker Space at olaservo/skills-over-mcp-demo:

https://olaservo-skills-over-mcp-demo.hf.space/mcp

Deployment lives in hf-space/: assemble.ps1 stages a self-contained bundle (source + skills + Dockerfile + Space README) into hf-space/.staging, then hf upload olaservo/skills-over-mcp-demo hf-space/.staging . --repo-type space pushes it. Verify the live endpoint with tsx src/smoke-http.ts https://olaservo-skills-over-mcp-demo.hf.space/mcp. Free CPU Spaces sleep after inactivity; the first request after a sleep is slow.

Deployment note: the first push got auto-flagged by HF's abuse handler (rule "Cloudflare" — tunnel-domain strings in a source docstring). Removing the trycloudflare.com references and recreating the Space cleared it; keep tunnel hostnames out of Space content.

Testing the OpenAI skills import (Scan Tools)

OpenAI imports skills server-side: during plugin submission, the developer portal's Scan Tools connects to your MCP server over streamable HTTP, runs skills/list / skills/get / resources/read, verifies digests, and snapshots the skills into the plugin draft. Codex and ChatGPT then receive skills from OpenAI's plugin backend, not from your server. The test ladder:

  1. Local validation with MCP Inspector (OpenAI's prescribed pre-submission check):

    npm run start:http                                     # terminal 1
    npx @modelcontextprotocol/inspector                    # terminal 2 → Streamable HTTP → http://127.0.0.1:3000/mcp
    # or non-interactive:
    npx @modelcontextprotocol/inspector --cli http://127.0.0.1:3000/mcp --transport http --method resources/list
  2. Expose publicly — the deployed Hugging Face Space above is the stable public endpoint. (Alternative: a quick tunnel — start one against http://localhost:3000, then restart the server with --allow-host <tunnel-hostname>.)

  3. Run Scan Tools in the OpenAI developer portal against https://olaservo-skills-over-mcp-demo.hf.space/mcp during plugin creation, then check the imported draft.

Result (2026-08-03): confirmed. Scan Tools imported all 3 listed skills with "Passed" validation; unlisted secret-menu did not import (the importer consumes only skills/list). Full findings — including the tools-surface requirement for ChatGPT connectors and the explicit-annotations validation — in docs/openai-plugin-submission.md. Expected: the 3 listed skills import with digests verified; secret-menu does not (their importer consumes only skills/list). Then exercise the plugin in ChatGPT developer mode.

The demo intentionally fits OpenAI's import limits (≤5 uniquely named skills, ≤100 files/skill, SKILL.md ≤256 KiB, files ≤1 MiB).

OpenAI skills import vs SEP-2640

OpenAI's MCP server plugin docs support importing skills from an MCP server, and their mechanism is recognizably SEP-2640 v1. Checked against the current SEP text (PR #2640, seps/2640-skills-extension.md):

Matches the SEP:

  • Capability declared at capabilities.extensions["io.modelcontextprotocol/skills"] — OpenAI's docs even call out that the earlier experimental location is wrong.

  • skills/list (paginated via nextCursor) returning uri, verbatim frontmatter (with required name and description), and a complete resources manifest; skills/get for single-entry retrieval; content fetched via resources/read.

  • Digest format sha256: + 64 lowercase hex chars; text resources hashed over the UTF-8 bytes of content.text, blob resources hashed over the base64-decoded bytes — exactly the SEP's raw-bytes rule.

  • Directory-name-equals-skill-name (the SEP's "final <skill-path> segment MUST equal frontmatter.name").

  • Import-time verification that fetched content matches digests and that SKILL.md frontmatter matches the catalog entry exactly — both host-side MUSTs in the SEP.

  • Rejecting skills whose resources aren't all fetchable/digestible — the SEP says hosts MAY decline skills without a resources manifest, and OpenAI does.

Differences (host policy or stricter-than-SEP):

  • skill:// treated as required. OpenAI says "use the skill:// URI convention." The SEP says servers SHOULD use skill:// but MAY serve skills under any scheme, and hosts MUST NOT infer skill-ness from the scheme. If OpenAI's scanner actually rejects non-skill:// URIs, that's stricter than the SEP — a conformant github://… skills server would fail import. Practical takeaway: stick to skill:// (as this demo does) for maximum compatibility.

  • Import limits are OpenAI policy, not SEP. ≤5 uniquely named skills per scan, ≤10 catalog pages, ≤100 files per skill, SKILL.md ≤256 KiB, supporting files ≤1 MiB, ≤5 MiB per skill — none of these appear in the SEP. A conformant server can exceed them and simply won't import fully.

  • Archives are OpenAI-internal. Their "generated archives per scan ≤8 MiB" limit refers to post-import packaging on their side. The SEP explicitly removed archive distribution from the wire protocol (see its Deferred Features appendix); no conflict, but worth knowing the archive never crosses the MCP connection.

  • Snapshot-only, listing-only. OpenAI imports at scan time and requires re-scanning to pick up changes — consistent with the SEP's point-in-time entries. But an import pipeline only consumes skills/list, so SEP features aimed at live hosts don't apply: unlisted skills (like this demo's secret-menu), the instructions pointer, and resources/directory/read are invisible to OpenAI's importer. Servers targeting OpenAI import should list everything they want imported.

Layout

src/server.ts      shared factory: loadSkills() + registerSkillResources()
src/index.ts       stdio entry point (serveStdio)
src/http.ts        streamable HTTP entry point (createMcpHandler + @modelcontextprotocol/node)
src/checks.ts      shared SEP-2640 client-side checks
src/smoke.ts       stdio smoke test
src/smoke-http.ts  streamable HTTP smoke test
skills/            the demo skills (Agent Skills format: SKILL.md + supporting files)
Install Server
F
license - not found
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • A registry of 5,900+ peer-authored skills any MCP agent can search and load on demand.

  • Hosted AgentLux MCP server for marketplace, identity, creator, services, and social flows.

  • Agent-native MCP server over the public saagarpatel.dev corpus. Read-only, stateless.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/olaservo/skills-over-mcp-demo'

If you have feedback or need assistance with the MCP directory API, please join our Discord server