Skills and MCP are two different extension systems in Seshat. Skills are reusable instruction packages that shape agent behavior inside the runtime. MCP is the protocol bridge that imports external tools, resources, and prompts into the runtime. They often work together, but they do not solve the same problem.
If you want the agent to behave differently, reach for a skill. If you want the agent to reach new systems or capabilities, reach for MCP. Skills are prompt-time behavior modules. MCP is runtime-time capability import.
Reusable prompt-time task definitions. They shape what the agent should do, when to do it, what context to inject, and which dependencies or hooks to consider.
Protocol-level integration with external servers. MCP extends what the runtime can actually call by importing remote tools, resources, and prompts.
Skills plug into prompt-time behavior and invocation flow. MCP plugs into the tool registry and external execution surface. Both end up inside the same session contract.
Frontmatter, triggers, hooks, and prompt bodies tell the runtime how to frame and route work.
New external tools and resources become callable without rewriting the core runtime.
This distinction keeps the architecture clean. You do not need to fork the runtime to teach it a reusable workflow, and you do not need to rewrite the prompt system to connect a database, GitHub, or any other MCP-compatible surface. The runtime owns both extension planes, but it owns them differently.
A skill is a Markdown file with YAML frontmatter. The frontmatter defines how the skill should be treated by the runtime, and the Markdown body becomes the injected instruction payload. In practice, a skill is a reusable task recipe that can carry triggers, allowed tools, execution context, dependency checks, shell hooks, and prompt scaffolding.
---
name: "summarise-pr"
description: "Summarise a pull request for the team."
when_to_use: "When the user asks for a PR summary or reviewer briefing."
allowed-tools:
- bash
- read
triggers:
- summarise this pull request
- review this pr
preamble-tier: standard
requires:
- type: node
check: "node --version"
install-cmd: "cd ${SESHAT_SKILL_DIR}/scripts && npm install"
---
Read the diff, inspect changed files, and write a concise reviewer briefing.Highest priority for repo-specific behavior.
Admin or policy-owned skills.
Personal skills for one user.
Compatibility and built-in local sources.
Cloned collections where each SKILL.md becomes a namespaced skill.
Lowest priority fallback.
The loader walks multiple sources and then deduplicates by skill name, so the first matching skill wins. That gives Seshat a stable override model: repo-owned behavior can beat user defaults, while bundled fallback skills stay at the bottom. It also means the same runtime can support personal skills, team skills, admin-managed skills, and cloned skill collections without inventing a second plugin system.
Another important detail is that cloned skill repositories are treated as collections. Each directory containing a SKILL.md becomes one namespaced skill, and ${SESHAT_SKILL_DIR} resolves to the collection root so the prompt can refer to repo-relative data or scripts.
Seshat does not hardcode a fixed list of skill commands into the model prompt. The skill tool rebuilds its own definition dynamically from the currently visible skills, marks itself as deferred, and tells the model to invoke it whenever a matching slash command or task-specific skill exists.
The runtime can keep the core prompt stable while still letting `tool_search` or the system reminder surface skill capabilities only when needed.
The loader can match a user request against trigger phrases before the user ever types a slash command explicitly.
Skills can be filtered by active file context when path restrictions are present.
Hooks and shell lifecycle blocks make skills act more like reusable workflows than static text macros.
The MCP side is much more transport- and protocol-oriented. The runtime reads config, connects to external servers, completes the MCP initialize handshake, discovers the remote surface, and then wraps it into Seshat's own tool registry.
{
"mcpServers": {
"github": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
}
},
"docs": {
"type": "sse",
"url": "https://example.com/mcp"
}
}
}The runtime reads `mcp.json` and `.mcp.json`, expands env vars, validates server definitions, and applies scope rules.
A client starts via stdio, HTTP, SSE, or WebSocket depending on the server config.
The initialize handshake completes, then Seshat lists the server's tools, resources, and prompts.
External capabilities are wrapped as native runtime tools, plus generic `mcp_list_resources` and `mcp_read_resource` helpers.
The session sees a flat tool surface. Deferred discovery through `tool_search` can still surface MCP tools when needed.
The wrapper does more than import tools. It also wraps resources and prompts, and it always adds generic resource helpers such as mcp_list_resources and mcp_read_resource. By default, exposed MCP tool names are prefixed like mcp__github__search_issues, although aliases are also generated for easier lookup.
MCP server definitions are loaded from runtime-root config as well as project-local config. In the current loader, enterprise config acts like an override path, while user and project-local definitions are merged when enterprise mode is not present. Environment variables inside config entries are expanded before connection.
<runtime-root>/mcp.json is the default user-level config.
.mcp.json in the working tree can define repo-specific servers.
The client currently supports stdio, HTTP, SSE, and WebSocket-backed remote servers.
Clients are started, initialized, tracked, and can be hot-reloaded by the SDK without recreating the whole runtime.
client, err := sdk.NewClient(&sdk.ClientConfig{
MCPServers: []sdk.MCPServerConfig{
{
Name: "github",
Transport: sdk.MCPTransportStdio,
Command: "npx",
Args: []string{"-y", "@modelcontextprotocol/server-github"},
},
},
})A strong pattern is to use a skill to define a repeatable workflow and an MCP server to provide the external systems that workflow needs. For example, a PR review skill can encode the review method while GitHub or Jira MCP servers provide the live project data.
There is even an MCP-to-skill bridge in the codebase that can expose connected MCP tools as skill-like invocations, but the main architectural path is still direct tool wrapping into the runtime registry.
This is one of the places where Seshat starts to look less like a single assistant and more like an extensible agent runtime. Skills let communities and teams package operating knowledge. MCP lets domain systems plug in without waiting for the core runtime to reimplement them one by one. Together, they create the extension surface that a broader agent platform actually needs.
Once the extension surface is clear, the next practical layer is how people actually use it day to day in the CLI app: sessions, settings, MCP management, and runtime workflows.