Skillgesture is a local MCP server for organizing and providing skills to AI agents. Skills are stored in a central repository, organized as group → skill → subskill, and loaded in full only when an agent requests them.
~/.skillgesture;npm install
To make the skillgesture command globally available during development:
npm link
npm start
The server uses the MCP stdio transport. Diagnostic messages are written to stderr, while stdout is reserved for the MCP protocol.
Example MCP client configuration:
{
"mcpServers": {
"skillgesture": {
"command": "node",
"args": ["/absolute/path/to/skillgesture/src/index.js"]
}
}
}
To use a different storage directory:
SKILLGESTURE_HOME=/alternative/path npm start
skill_manageManages sessions, the catalog, and associations. The available actions are:
session.opensession.configuresession.listgroup.upsertskill.upsertsubskill.upsertnode.setEnabledassociation.setskill_treeReturns the lightweight tree of skills applicable to a session. It includes metadata and provenance, but not Markdown content.
skill_readReads the Markdown of a single active skill or subskill on demand. If the skill contains imported supporting files, the first read also returns their resources index. Passing one of those paths as resourcePath reads only that resource without loading the entire bundle into the context.
Each agent creates a session once:
{
"action": "session.open",
"data": {
"label": "coding-agent",
"folders": [
"/Users/example/projects/api",
"/Users/example/projects/shared"
]
}
}
The response contains a UUID:
{
"ok": true,
"session": {
"sessionId": "6de1fdba-aec8-4dc7-b03c-1e21e1ae58ac"
},
"resumed": false
}
The agent must retain and reuse this sessionId.
After restarting the server:
{
"action": "session.open",
"data": {
"sessionId": "6de1fdba-aec8-4dc7-b03c-1e21e1ae58ac"
}
}
An unknown ID does not implicitly create a new session.
{
"action": "session.configure",
"data": {
"sessionId": "6de1fdba-aec8-4dc7-b03c-1e21e1ae58ac",
"mode": "add",
"folders": ["/Users/example/projects/another-project"]
}
}
mode can be replace, add, or remove.
{
"sessionId": "6de1fdba-aec8-4dc7-b03c-1e21e1ae58ac",
"includeDisabled": false
}
{
"sessionId": "6de1fdba-aec8-4dc7-b03c-1e21e1ae58ac",
"groupId": "coding",
"skillId": "nodejs",
"subskillId": "testing"
}
subskillId is optional.
To read a resource listed in the previous response:
{
"sessionId": "6de1fdba-aec8-4dc7-b03c-1e21e1ae58ac",
"groupId": "coding",
"skillId": "nodejs",
"resourcePath": "references/testing.md"
}
Text resources are returned as UTF-8; binary resources are returned as Base64.
{
"action": "group.upsert",
"data": {
"id": "coding",
"name": "Coding",
"description": "Development skills"
}
}
{
"action": "skill.upsert",
"data": {
"groupId": "coding",
"id": "git",
"name": "Git",
"description": "Version control management",
"global": true,
"markdown": "# Git\n\nSkill instructions."
}
}
{
"action": "skill.upsert",
"data": {
"groupId": "coding",
"id": "nodejs",
"name": "Node.js",
"global": false,
"markdown": "# Node.js\n\nSkill instructions."
}
}
{
"action": "subskill.upsert",
"data": {
"groupId": "coding",
"skillId": "nodejs",
"id": "testing",
"name": "Node testing",
"markdown": "# Node testing\n\nUse node:test."
}
}
Subskills inherit the scope of their parent skill.
{
"action": "association.set",
"data": {
"folder": "/Users/example/projects/api",
"skills": [
{
"groupId": "coding",
"skillId": "nodejs"
}
]
}
}
association.set replaces the folder's entire set of skills. An empty array removes the association.
Associations are based on the exact canonical path:
/projects/api does not automatically apply to /projects/api/packages/web;{
"action": "node.setEnabled",
"data": {
"ref": {
"groupId": "coding",
"skillId": "nodejs"
},
"enabled": false
}
}
Disabling a group disables all its descendant skills. Disabling a skill also makes its subskills unreadable. skill_tree can show disabled nodes when called with includeDisabled: true.
Multiple MCP processes can use the same repository. Sessions are stored separately, and mutations are serialized through a cross-process lock.
Update operations accept expectedVersion; association.set accepts expectedRevision. If another agent has already changed the data, Skillgesture returns VERSION_CONFLICT instead of silently overwriting the change.
~/.skillgesture/
├── catalog.json
├── associations.json
├── sessions/
│ └── <session-id>.json
└── skills/
└── <group-id>/
└── <skill-id>/
├── versions/
│ └── <version>/
│ ├── SKILL.md
│ └── resources/
└── subskills/
└── <subskill-id>/
└── versions/
└── <version>/
├── SKILL.md
└── resources/
Markdown versions are immutable. The catalog points to the active version, preventing reads from observing partially updated content.
npm test
Tests use temporary directories and do not modify ~/.skillgesture.
ISC
6 commits
JavaScript
100.0%
Skillgesture is a local MCP server for organizing and providing skills to AI agents. Skills are stored in a central repository, organized as group → skill → subskill, and loaded in full only when an agent requests them.
~/.skillgesture;npm install
To make the skillgesture command globally available during development:
npm link
npm start
The server uses the MCP stdio transport. Diagnostic messages are written to stderr, while stdout is reserved for the MCP protocol.
Example MCP client configuration:
{
"mcpServers": {
"skillgesture": {
"command": "node",
"args": ["/absolute/path/to/skillgesture/src/index.js"]
}
}
}
To use a different storage directory:
SKILLGESTURE_HOME=/alternative/path npm start
skill_manageManages sessions, the catalog, and associations. The available actions are:
session.opensession.configuresession.listgroup.upsertskill.upsertsubskill.upsertnode.setEnabledassociation.setskill_treeReturns the lightweight tree of skills applicable to a session. It includes metadata and provenance, but not Markdown content.
skill_readReads the Markdown of a single active skill or subskill on demand. If the skill contains imported supporting files, the first read also returns their resources index. Passing one of those paths as resourcePath reads only that resource without loading the entire bundle into the context.
Each agent creates a session once:
{
"action": "session.open",
"data": {
"label": "coding-agent",
"folders": [
"/Users/example/projects/api",
"/Users/example/projects/shared"
]
}
}
The response contains a UUID:
{
"ok": true,
"session": {
"sessionId": "6de1fdba-aec8-4dc7-b03c-1e21e1ae58ac"
},
"resumed": false
}
The agent must retain and reuse this sessionId.
After restarting the server:
{
"action": "session.open",
"data": {
"sessionId": "6de1fdba-aec8-4dc7-b03c-1e21e1ae58ac"
}
}
An unknown ID does not implicitly create a new session.
{
"action": "session.configure",
"data": {
"sessionId": "6de1fdba-aec8-4dc7-b03c-1e21e1ae58ac",
"mode": "add",
"folders": ["/Users/example/projects/another-project"]
}
}
mode can be replace, add, or remove.
{
"sessionId": "6de1fdba-aec8-4dc7-b03c-1e21e1ae58ac",
"includeDisabled": false
}
{
"sessionId": "6de1fdba-aec8-4dc7-b03c-1e21e1ae58ac",
"groupId": "coding",
"skillId": "nodejs",
"subskillId": "testing"
}
subskillId is optional.
To read a resource listed in the previous response:
{
"sessionId": "6de1fdba-aec8-4dc7-b03c-1e21e1ae58ac",
"groupId": "coding",
"skillId": "nodejs",
"resourcePath": "references/testing.md"
}
Text resources are returned as UTF-8; binary resources are returned as Base64.
{
"action": "group.upsert",
"data": {
"id": "coding",
"name": "Coding",
"description": "Development skills"
}
}
{
"action": "skill.upsert",
"data": {
"groupId": "coding",
"id": "git",
"name": "Git",
"description": "Version control management",
"global": true,
"markdown": "# Git\n\nSkill instructions."
}
}
{
"action": "skill.upsert",
"data": {
"groupId": "coding",
"id": "nodejs",
"name": "Node.js",
"global": false,
"markdown": "# Node.js\n\nSkill instructions."
}
}
{
"action": "subskill.upsert",
"data": {
"groupId": "coding",
"skillId": "nodejs",
"id": "testing",
"name": "Node testing",
"markdown": "# Node testing\n\nUse node:test."
}
}
Subskills inherit the scope of their parent skill.
{
"action": "association.set",
"data": {
"folder": "/Users/example/projects/api",
"skills": [
{
"groupId": "coding",
"skillId": "nodejs"
}
]
}
}
association.set replaces the folder's entire set of skills. An empty array removes the association.
Associations are based on the exact canonical path:
/projects/api does not automatically apply to /projects/api/packages/web;{
"action": "node.setEnabled",
"data": {
"ref": {
"groupId": "coding",
"skillId": "nodejs"
},
"enabled": false
}
}
Disabling a group disables all its descendant skills. Disabling a skill also makes its subskills unreadable. skill_tree can show disabled nodes when called with includeDisabled: true.
Multiple MCP processes can use the same repository. Sessions are stored separately, and mutations are serialized through a cross-process lock.
Update operations accept expectedVersion; association.set accepts expectedRevision. If another agent has already changed the data, Skillgesture returns VERSION_CONFLICT instead of silently overwriting the change.
~/.skillgesture/
├── catalog.json
├── associations.json
├── sessions/
│ └── <session-id>.json
└── skills/
└── <group-id>/
└── <skill-id>/
├── versions/
│ └── <version>/
│ ├── SKILL.md
│ └── resources/
└── subskills/
└── <subskill-id>/
└── versions/
└── <version>/
├── SKILL.md
└── resources/
Markdown versions are immutable. The catalog points to the active version, preventing reads from observing partially updated content.
npm test
Tests use temporary directories and do not modify ~/.skillgesture.
ISC
6 commits
JavaScript
100.0%