Skip to main content
Glama
README.md
# CC MCP

A Common Cartridge 1.4 specification reference MCP server for building Common Cartridge 1.4 course packages. Give your MCP-compatible assistant searchable specification text, implementation guidance, and XML schema definitions for manifests, metadata, resources, and more.

Read-only, local, and offline after installation. Includes a ready-to-use reference index; no API keys required. This is a reference lookup service, not a package validator or certification tool.

## Launch locally

Requires Python 3.11+ with SQLite FTS5 support (included in standard Python distributions).

```sh
git clone https://github.com/JustinPack/CC-MCP.git
cd CC-MCP
python3 -m venv .venv
.venv/bin/python -m pip install -r requirements.txt
.venv/bin/python server/mcp_server.py
```

On Windows PowerShell, after cloning and entering the folder:

```powershell
py -3 -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
.\.venv\Scripts\python.exe server\mcp_server.py
```

The server uses **stdio**, not HTTP. It waits silently for an MCP client and exits when stdin closes. Normally, your client launches it using a configuration like this:

```json
{
  "mcpServers": {
    "cc-mcp": {
      "command": "/absolute/path/CC-MCP/.venv/bin/python",
      "args": ["/absolute/path/CC-MCP/server/mcp_server.py"]
    }
  }
}
```

Use absolute paths. On Windows, use `C:/path/CC-MCP/.venv/Scripts/python.exe` and `C:/path/CC-MCP/server/mcp_server.py`. Configuration location and format depend on your MCP client.

## Launch with Docker

From the cloned folder:

```sh
docker build -t cc-mcp .
docker run --rm -i --read-only --network none \
  --cap-drop=ALL --security-opt=no-new-privileges cc-mcp
```

For a client-managed container, replace the `cc-mcp` entry above with:

```json
{
  "command": "docker",
  "args": [
    "run", "--rm", "-i", "--read-only", "--network", "none",
    "--cap-drop=ALL", "--security-opt=no-new-privileges", "cc-mcp"
  ]
}
```

Keep `-i`; do not add `-t`. No ports or volumes are needed. The image runs as
an unprivileged user and its application files and reference database are
read-only. This is a stdio MCP server, so deploy it as a client-managed
`docker run` process rather than as a port-based Compose or web service.

## Reference requests

Ask your connected assistant, for example:

- “Use CC MCP to find the manifest metadata requirements for a Common Cartridge 1.4 course package. Cite the reference sections.”
- “Look up the CC1.4 `manifest` schema declaration and explain its required attributes.”

| Tool | Purpose |
| --- | --- |
| `search_spec` | Ranked keyword search; `scope`: `core`, `schema`, `dependency`, or `all`. |
| `get_section` | Read a section using a `section_ref` returned by search. |
| `lookup_definition` | Find schema declarations and relevant prose for a term. |
| `get_schema_component` | Get an XSD declaration by exact namespace and name. |
| `list_documents` | List available documents; `kind` uses the same values as `scope`. |

For direct MCP clients, these are JSON-RPC `tools/call` requests **after the MCP initialization handshake**. Send one JSON object per line over stdio, not as HTTP requests:

```jsonl
{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"search_spec","arguments":{"query":"manifest","scope":"core","limit":3}}}
{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"get_section","arguments":{"section_id":"057c26e3f89a0c24f07f2b31b614d1c5bf8369f329129c3d55c6fd73af5fe467::h3-8-2-manifest-level-metadata"}}}
{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"lookup_definition","arguments":{"term":"resource"}}}
{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"get_schema_component","arguments":{"namespace":"http://www.imsglobal.org/xsd/imsccv1p4/imscp_v1p1","name":"manifest"}}}
{"jsonrpc":"2.0","id":5,"method":"tools/call","params":{"name":"list_documents","arguments":{"kind":"core"}}}
```

Search returns source URLs, excerpts, and `section_ref` values. The second request reads a section returned by the first. For other lookups, pass the returned `section_ref` as `section_id`. Sections are paged at 8,000 characters; resend the same `section_id` with `"cursor":"<next_cursor>"` until `next_cursor` is `null`. Results include JSON in `structuredContent` and a text equivalent in `content`.

## License

Server code: [MIT](LICENSE). Bundled reference material retains its upstream terms; see [NOTICE.md](NOTICE.md). Independent project, not affiliated with or endorsed by 1EdTech.