feat: add AI Workspace Menu Bar App design and enhance MCP server with resource definitions and read functionality

This commit is contained in:
2026-05-20 15:22:37 -06:00
parent cfd61bdee3
commit b21889c4ab
8 changed files with 368 additions and 43 deletions

View File

@@ -295,6 +295,75 @@ def photos_latest(args: dict[str, Any]) -> dict[str, Any]:
return tool_result({"profile": profile, "source": "photo-inbox", "canonical": False, "photos": photos})
def resource_definitions() -> list[dict[str, Any]]:
resources: list[dict[str, Any]] = []
for profile in sorted(path.name for path in (ROOT / "profiles").iterdir() if (path / "profile.md").is_file()):
resources.extend([
{
"uri": f"aiw://profiles/{profile}/current-work",
"name": f"{profile}-current-work",
"title": f"{profile} Current Work",
"description": "Canonical current work context.",
"mimeType": "text/markdown",
"annotations": {"audience": ["assistant"], "priority": 0.95},
},
{
"uri": f"aiw://profiles/{profile}/work-items",
"name": f"{profile}-work-items",
"title": f"{profile} Active Work Items",
"description": "Canonical active work-item summary.",
"mimeType": "text/markdown",
"annotations": {"audience": ["assistant"], "priority": 0.9},
},
{
"uri": f"aiw://profiles/{profile}/mattermost/latest",
"name": f"{profile}-mattermost-latest",
"title": f"{profile} Mattermost Latest",
"description": "Profile-filtered latest Mattermost mirror evidence as JSON.",
"mimeType": "application/json",
"annotations": {"audience": ["assistant"], "priority": 0.75},
},
{
"uri": f"aiw://profiles/{profile}/photos/latest",
"name": f"{profile}-photos-latest",
"title": f"{profile} Photo Inbox Latest",
"description": "Latest local Photo Inbox file metadata as JSON; image data is not embedded.",
"mimeType": "application/json",
"annotations": {"audience": ["assistant"], "priority": 0.45},
},
])
return resources
def read_resource(uri: str) -> dict[str, Any] | None:
parsed = urllib.parse.urlparse(uri)
if parsed.scheme != "aiw":
return None
parts = [part for part in parsed.path.split("/") if part]
if parsed.netloc != "profiles" or len(parts) < 2:
return None
profile = parts[0]
resource = "/".join(parts[1:])
base = knowledge_dir(profile)
if resource == "current-work":
path = base / "01-current" / "current-work.md"
if not path.is_file():
return None
return {"uri": uri, "mimeType": "text/markdown", "text": path.read_text(encoding="utf-8", errors="replace")}
if resource == "work-items":
path = base / "01-current" / "work-items.md"
if not path.is_file():
return None
return {"uri": uri, "mimeType": "text/markdown", "text": path.read_text(encoding="utf-8", errors="replace")}
if resource == "mattermost/latest":
data = communication_latest({"profile": profile, "limit": 80})["structuredContent"]
return {"uri": uri, "mimeType": "application/json", "text": json.dumps(data, ensure_ascii=False, indent=2, sort_keys=True)}
if resource == "photos/latest":
data = photos_latest({"profile": profile, "limit": 30})["structuredContent"]
return {"uri": uri, "mimeType": "application/json", "text": json.dumps(data, ensure_ascii=False, indent=2, sort_keys=True)}
return None
TOOLS: dict[str, dict[str, Any]] = {
"context_profiles": {"handler": list_profiles, "description": "List AI Workspace project profiles.", "properties": {}},
"communication_latest": {"handler": communication_latest, "description": "Read bounded latest Mattermost mirror evidence, filtered to the profile's context channels by default.", "properties": {"profile": {"type": "string"}, "channels": {"type": "string"}, "include_all_channels": {"type": "boolean"}, "limit": {"type": "integer"}}},
@@ -342,7 +411,7 @@ def handle_request(message: dict[str, Any]) -> dict[str, Any] | None:
requested = str(params.get("protocolVersion") or PROTOCOL_VERSION)
return jsonrpc_response(request_id, {
"protocolVersion": requested if requested in {PROTOCOL_VERSION, "2025-03-26"} else PROTOCOL_VERSION,
"capabilities": {"tools": {"listChanged": False}},
"capabilities": {"tools": {"listChanged": False}, "resources": {"listChanged": False}},
"serverInfo": {"name": SERVER_NAME, "title": "AI Workspace Context MCP", "version": SERVER_VERSION},
"instructions": "Read-only local AI Workspace context. Evidence is not canonical memory unless promoted by the agent/user.",
})
@@ -350,6 +419,16 @@ def handle_request(message: dict[str, Any]) -> dict[str, Any] | None:
return jsonrpc_response(request_id, {})
if method == "tools/list":
return jsonrpc_response(request_id, {"tools": tool_definitions()})
if method == "resources/list":
return jsonrpc_response(request_id, {"resources": resource_definitions()})
if method == "resources/read":
uri = str(params.get("uri") or "")
content = read_resource(uri)
if content is None:
return jsonrpc_error(request_id, -32002, "Resource not found", {"uri": uri})
return jsonrpc_response(request_id, {"contents": [content]})
if method == "resources/templates/list":
return jsonrpc_response(request_id, {"resourceTemplates": []})
if method == "tools/call":
name = str(params.get("name") or "")
arguments = params.get("arguments") or {}