Files
agentic-mobile-control/openspec/changes/skill-management-console/specs/skill-mcp-tools/spec.md
T
q792602257andClaude Opus 4.6 dd03abbbb0 feat(skills): open skill-management-console change + local skill store
Opens the skill-management-console openspec change (cloud/local skill split
with local override) with proposal, design (D1-D11), four delta specs, and
tasks. Implements the agent-side persistent local skill store
(storage/local_skills.py): authored local skills + cloud-skill overrides in
a physically separate SQLite file, with fork-on-revocation. 10 tests pass.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-07-15 07:28:42 +08:00

47 lines
3.9 KiB
Markdown

## MODIFIED Requirements
### Requirement: MCP tools for skill discovery and retrieval
The system SHALL expose `list_skills`, `search_skills`, and `get_skill` as MCP tools on the same MCP server surface used for device capabilities. The tools SHALL present a unified catalog merged from cloud-synced skills and local skills (delegating to the `local-skill-management` read-merge surface), and SHALL return each skill with an `origin` of `"cloud"` or `"local"` and a `locally_overridden` flag when a local override shadows a cloud skill. The responses SHALL NOT expose any entitlement, subscription, or cloud-management-internal fields to the LLM.
#### Scenario: LLM lists available skills across both origins
- **WHEN** an MCP client calls `list_skills`
- **THEN** it receives the merged set of cloud-synced and local skills visible to it, each with id, name, description, kind, tags, `origin`, and `locally_overridden`
#### Scenario: LLM searches across both origins
- **WHEN** an MCP client calls `search_skills` with a query string
- **THEN** it receives matching skills from both origins ranked by relevance, each tagged with `origin`
#### Scenario: LLM fetches a skill, observing any active override
- **WHEN** an MCP client calls `get_skill` with a skill id that has an active local override
- **THEN** it receives the override's content, tagged `origin = "cloud"` and `locally_overridden = true`
### Requirement: Skill MCP errors are semantic
The system SHALL translate skill-level errors (skill not found, skill not visible/entitled, invalid/unavailable flow template, and authoring errors such as attempting to delete a cloud skill with no override) into clear, semantic MCP tool error responses, consistent in style with the device-capability tool error handling. A request for a cloud skill that is unknown or not visible to the caller SHALL produce an indistinguishable not-found error (no existence leak).
#### Scenario: Requesting a non-visible cloud skill
- **WHEN** `get_skill` is called with a cloud skill id that exists but is not visible to the caller's host and has no override
- **THEN** the tool returns a semantic "not found" error rather than a raw database or internal exception
#### Scenario: Deleting a cloud skill that has no override
- **WHEN** `delete_skill` is called with a cloud skill id that has no local override
- **THEN** the tool returns a semantic error indicating there is no local override to remove, without revoking any cloud entitlement
## ADDED Requirements
### Requirement: Authoring MCP tools dispatch by origin
The system SHALL expose `create_skill`, `update_skill`, and `delete_skill` as MCP tools on the agent's MCP server, always registered (no enable/disable gate). Their behaviour SHALL dispatch by the target skill's origin: `create_skill` creates a new local skill; `update_skill` edits a local skill or creates/updates a local override for a cloud skill; `delete_skill` deletes a local skill or removes a local override for a cloud skill. None of these tools SHALL ever write to the synced store or mutate a cloud skill directly; override semantics are governed by the `local-skill-management` capability.
#### Scenario: Create a new local skill
- **WHEN** the LLM calls `create_skill` with content for a new skill
- **THEN** a new local skill is created with `origin = "local"` and is thereafter discoverable via the read tools
#### Scenario: Update dispatches by origin
- **WHEN** the LLM calls `update_skill` with a local skill id
- **THEN** the local skill is edited; and **WHEN** called with a cloud skill id
- **THEN** a local override for that cloud id is created or updated (the cloud/synced store is untouched)
#### Scenario: Delete dispatches by origin
- **WHEN** the LLM calls `delete_skill` with a local skill id
- **THEN** the local skill is deleted; and **WHEN** called with a cloud skill id that has an override
- **THEN** the override is removed and the cloud skill resurfaces on the next read