Skip to content

feat(mcp): organize artifact directory by action type instead of flat dump #43

@jmagar

Description

@jmagar

Summary

MCP artifacts are currently written flat to the artifact root directory (.cache/axon-mcp/ or $AXON_MCP_ARTIFACT_DIR) with no subdirectory organization. After moderate use, the directory accumulates 130+ files with no structure — making it difficult to find, manage, or clean up artifacts by type.

Current state (flat dump):

.cache/axon-mcp/
├── ask-how-do-i-configure-crawl-depth-and-concurrency-in-axon.json
├── crawl-list.json
├── crawl-status-0befcb87-08f2-49e0-b88c-5079a121f33b.json
├── crawl-status-1c76379f-d86e-42ed-8f08-b20902c92bed.json
├── discover-sitemaps-example-com.json
├── embed-status-abc123.json
├── help-actions.json
├── map-example-com.json
├── ops-doctor.json
├── query-result.json
├── rag-answer.json
├── research-topic-name.json
├── retrieve-https-docs-example-com.json
├── scrape-https-example-com-page.json
├── search-some-query-terms.json
├── smoke-mcporter.json
└── ... (130 files, growing)

Proposed structure — organize by action type:

.cache/axon-mcp/
├── ask/
│   └── how-do-i-configure-crawl-depth.json
├── crawl/
│   ├── list.json
│   └── status-0befcb87.json
├── discover/
│   └── sitemaps-example-com.json
├── embed/
│   └── status-abc123.json
├── extract/
│   └── items-example-com.json
├── map/
│   └── example-com.json
├── ops/
│   └── doctor.json
├── query/
│   └── result.json
├── rag/
│   └── answer.json
├── research/
│   └── topic-name.json
├── retrieve/
│   └── docs-example-com.json
├── scrape/
│   └── example-com-page.json
├── screenshots/          # already uses subdirectory ✓
│   └── domain_com.png
└── search/
    └── query-terms.json

Current artifact type distribution (real usage)

Prefix Count
rag- 19
crawl- 19
scrape- 17
ask- 17
retrieve- 16
search- 10
query- 8
discover- 7
research- 5
embed- 5
ops- 2
map- 2
help- 1

Key files to modify

  1. crates/mcp/server/artifacts/respond.rswrite_json_artifact(stem, payload) currently writes {artifact_root}/{stem}.json. Change to parse the action prefix from the stem and write to {artifact_root}/{action}/{remainder}.json, ensuring parent dir exists via create_dir_all.

  2. crates/mcp/server/artifacts/lifecycle.rsartifacts list currently does a non-recursive directory read. Update to walk subdirectories (one level deep) and include the subdirectory name in the returned path. artifacts search and artifacts clean also need recursive enumeration.

  3. crates/mcp/server/artifacts/path.rsvalidate_artifact_path() already allows nested paths, but resolve_artifact_output_path() may need adjustment to accept action/filename shapes.

Design considerations

  • Backward compatibility: On startup or first write, optionally migrate existing flat files into subdirectories (move ask-foo.jsonask/foo.json). Or just let old files age out via artifacts clean.
  • Stem parsing: The action prefix is already the first segment before the first - in every stem (e.g., ask-how-do-i... → action=ask, remainder=how-do-i...). This is a natural split point.
  • Screenshots already organized: The screenshots/ subdirectory pattern already exists and works — this extends the same approach to all artifact types.
  • artifacts list response: Include the subdirectory in the path field so callers can still read artifacts by their full relative path.
  • Auto-inline threshold: No changes needed — the inline vs. path decision happens before the path is constructed.

Acceptance criteria

  • Artifacts written to {root}/{action}/{name}.json instead of {root}/{action}-{name}.json
  • artifacts list returns all artifacts across subdirectories
  • artifacts search searches across subdirectories
  • artifacts clean cleans across subdirectories
  • artifacts read/head/grep/wc/delete work with both flat paths and nested paths
  • Existing flat artifacts still readable (no breaking change for in-flight usage)
  • screenshots/ subdirectory behavior unchanged

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions