Imported from anysiteio/agent-skills (
skills/anysite-mcp-migration/SKILL.md). Install upstream withnpx skills add anysiteio/agent-skills --skill anysite-mcp-migration. Copyright stays with the author.
anysite MCP Migration Assistant
Migrate your anysite MCP skills, prompts, and agent instructions from v1 (individual tools) to v2 (universal meta-tools).
Overview
Anysite MCP v2 replaces 70+ individual tools with 5 universal meta-tools. This skill helps you:
- Rewrite tool references from old format (
search_linkedin_users,get_linkedin_profile) to newexecute()calls - Add new v2 capabilities like pagination, server-side filtering, aggregation, and file export
- Validate migrated output to ensure nothing was missed
- Preserve workflow logic while updating only the tool interface layer
When to Use
- User says "migrate my skill to v2", "update for new anysite API", "convert to execute format"
- User pastes a skill or prompt that contains old-style tool names (
search_*,get_*,find_*) - User asks how to use new anysite MCP features (pagination, cache queries, export)
Migration Workflow
Step 1: Receive Input
Ask the user for one of:
- A skill file path — read the SKILL.md and any files in
references/ - Pasted prompt text — the raw text of their prompt or instruction
- A description of what the skill does — you'll help build it from scratch using v2 format
Step 2: Identify Old Tool References
Scan the input for any of these v1 tool name patterns:
| Pattern | Example |
|---|---|
search_linkedin_* |
search_linkedin_users, search_linkedin_companies, search_linkedin_jobs, search_linkedin_posts |
get_linkedin_* |
get_linkedin_profile, get_linkedin_company, get_linkedin_user_posts |
find_linkedin_* |
find_linkedin_email, find_linkedin_user_email |
google_linkedin_* |
google_linkedin_search |
search_twitter_* / get_twitter_* |
search_twitter_users, get_twitter_user, get_twitter_user_tweets |
search_instagram_* / get_instagram_* |
search_instagram_users, get_instagram_user, get_instagram_post |
search_youtube_* / get_youtube_* |
search_youtube, get_youtube_channel, get_youtube_video |
search_reddit_* / get_reddit_* |
search_reddit, get_reddit_user, get_reddit_posts |
search_yc_* / get_yc_* |
search_yc_companies, get_yc_company |
search_sec_* / get_sec_* |
search_sec_filings, get_sec_document |
scrape_webpage |
scrape_webpage |
mcp__anysite__* |
Any tool with the MCP prefix — strip prefix and match above |
Also look for references to Crunchbase — this source is disabled in v2 and must be removed.
Step 3: Apply Tool Mapping
Replace each old tool call using this mapping:
| Old tool | New execute() call |
|---|---|
search_linkedin_users(keywords, location, count, ...) |
execute("linkedin", "search", "search_users", {"keywords": ..., "location": ..., "count": ...}) |
get_linkedin_profile(user) |
execute("linkedin", "user", "get", {"user": ...}) |
get_linkedin_company(company) |
execute("linkedin", "company", "get", {"company": ...}) |
search_linkedin_companies(keywords, count) |
execute("linkedin", "search", "search_companies", {"keywords": ..., "count": ...}) |
search_linkedin_jobs(keywords, location, count) |
execute("linkedin", "job_search", "search_jobs", {"keywords": ..., "count": ...}) |
search_linkedin_posts(keywords, count) |
execute("linkedin", "post", "search_posts", {"keywords": ..., "count": ...}) |
get_linkedin_user_posts(user) |
execute("linkedin", "post", "get_user_posts", {"user": ...}) |
find_linkedin_email(user) |
execute("linkedin", "email", "find", {"user": ...}) |
google_linkedin_search(query, count) |
execute("linkedin", "google", "search", {"query": ..., "count": ...}) |
Twitter/X
| Old tool | New execute() call |
|---|---|
search_twitter_users(query) |
execute("twitter", "search", "search_users", {"query": ...}) |
get_twitter_user(username) |
execute("twitter", "user", "get", {"username": ...}) |
get_twitter_user_tweets(username) |
execute("twitter", "user_tweets", "get", {"username": ...}) |
| Old tool | New execute() call |
|---|---|
search_instagram_users(query) |
execute("instagram", "search", "search_users", {"query": ...}) |
get_instagram_user(username) |
execute("instagram", "user", "get", {"username": ...}) |
get_instagram_post(url) |
execute("instagram", "post", "get", {"url": ...}) |
YouTube
| Old tool | New execute() call |
|---|---|
search_youtube(query, count) |
execute("youtube", "search", "search_videos", {"query": ..., "count": ...}) |
get_youtube_channel(channel_id) |
execute("youtube", "channel", "get", {"channel_id": ...}) |
get_youtube_video(video_id) |
execute("youtube", "video", "get", {"video_id": ...}) |
| Old tool | New execute() call |
|---|---|
search_reddit(query) |
execute("reddit", "search", "search", {"query": ...}) |
get_reddit_user(username) |
execute("reddit", "user", "get", {"username": ...}) |
get_reddit_posts(subreddit) |
execute("reddit", "posts", "get", {"subreddit": ...}) |
YC / SEC / Web
| Old tool | New execute() call |
|---|---|
search_yc_companies(query) |
execute("yc", "search", "search", {"query": ...}) |
get_yc_company(slug) |
execute("yc", "company", "get", {"slug": ...}) |
search_sec_filings(query) |
execute("sec", "search", "search", {"query": ...}) |
get_sec_document(url) |
execute("sec", "document", "get", {"url": ...}) |
scrape_webpage(url) |
execute("webparser", "parse", "parse", {"url": ...}) |
Step 4: Handle Unknown Endpoints
If the input references a tool name not in the mapping above:
- Try to infer the source and category from the tool name (e.g.,
get_instagram_user_friendships→ source"instagram", category"user"or"friendship") - IMPORTANT: Actually call
discover()yourself right now — do NOT leave placeholder{endpoint}in the migrated output. Rundiscover("{source}", "{category}")via the MCP tool to get the real endpoint names and parameter schemas. - If the first category guess returns "Category not found", try alternative categories (e.g., if
"friendship"fails, try"user"— the endpoint may be nested under a different category) - Once you get the real endpoint list from
discover(), use the exact endpoint name and params in the migratedexecute()call
Example — resolving an unknown tool:
Old tool: get_instagram_user_friendships(user, type, count)
→ Not in mapping table
→ You call: discover("instagram", "friendship") → error "Category not found"
→ You call: discover("instagram", "user") → returns endpoints including "user_friendships"
→ Migrated: execute("instagram", "user", "user_friendships", {"user": "...", "count": 100, "type": "followers"})
Rules:
- NEVER leave
discover()as a placeholder instruction in the final migrated skill. The migrated output must contain exactexecute()calls with real endpoint names and params. - Only include
discover()in the migrated skill text if the skill's workflow genuinely needs runtime discovery (e.g., the skill works with user-specified sources where the endpoint can't be known at migration time). - If the mapping above covers the tool, use
execute()directly — no discover needed. - Run discover for ALL sources and categories used by the skill to verify that endpoint names and params in the mapping table are still accurate.
Step 5: Add v2 Capabilities
Review the migrated skill for opportunities to add new v2 features:
Pagination
When the workflow processes large result sets or needs "more results":
Results from execute() include cache_key. If more data exists, use:
get_page(cache_key="{cache_key}", offset=10, limit=10)
Server-side Filtering
When the workflow filters results after fetching (e.g., "only show people in SF"):
After execute(), filter without consuming context tokens:
query_cache(cache_key="{cache_key}", conditions=[{"field": "location", "op": "contains", "value": "San Francisco"}])
Aggregation
When the workflow computes statistics or groups data:
query_cache(cache_key="{cache_key}", aggregate={"field": "followers", "op": "avg"}, group_by="industry")
Export to File
When the workflow outputs structured data (CSV, JSON) or the user needs downloadable results:
export_data(cache_key="{cache_key}", output_format="csv")
→ returns download URL
Step 6: Update Error Handling
Replace old-style error handling:
Before:
If search_linkedin_users returns an error, try with different keywords.
After:
If execute() returns an error with "llm_hint", follow the hint.
If execute() returns {"error": "Source not found", "available_sources": [...]}, check source name.
If execute() returns {"error": "Endpoint not found", "available_endpoints": [...]}, call discover() to find correct endpoint names.
Step 7: Remove Disabled Sources
Remove any references to Crunchbase — this source is disabled in v2. If the skill relies on Crunchbase data, suggest alternatives:
- Company data → LinkedIn company profiles or Y Combinator
- Funding data → SEC filings or web scraping of funding databases
- Startup research → Y Combinator database
Step 8: Validate
Run through this checklist on the migrated output:
- No remaining
search_linkedin_*,get_linkedin_*,find_linkedin_*references - No remaining
search_twitter_*,get_twitter_*references - No remaining
search_instagram_*,get_instagram_*references - No remaining
search_youtube_*,get_youtube_*references - No remaining
search_reddit_*,get_reddit_*references - No remaining
search_yc_*,get_yc_*references - No remaining
search_sec_*,get_sec_*references - No remaining
scrape_webpagereferences - No remaining
mcp__anysite__prefixed tool names (old MCP format) - No Crunchbase references
-
discover()added only where endpoint/params are genuinely unknown -
get_page/query_cache/export_dataadded where beneficial - Error handling updated to v2 format
- Original workflow logic preserved — same steps, same data flow
Step 9: Output
Present the migrated skill in the same format as the input:
- If the input was a SKILL.md file → output the full migrated SKILL.md
- If the input was a prompt → output the migrated prompt text
- If the input was pasted text → output the migrated version
Always show a migration summary after the output:
## Migration Summary
- Tool calls replaced: N
- discover() calls added: N
- New v2 features added: [list]
- Crunchbase references removed: N
- Warnings: [any issues found]
Examples
Example 1: Simple Tool Replacement
Input:
Use search_linkedin_users to find CTOs in Berlin, then get_linkedin_profile for each result.
Output:
Use execute("linkedin", "search", "search_users", {"title": "CTO", "location": "Berlin", "count": 10}) to find CTOs in Berlin, then execute("linkedin", "user", "get", {"user": "{alias}"}) for each result.
Example 2: Multi-Step Workflow
Input:
1. Use search_linkedin_users to find the person
2. Use get_linkedin_profile to get their full profile
3. Use find_linkedin_email to get their email
4. Use get_twitter_user to check their Twitter
Output:
1. Use execute("linkedin", "search", "search_users", {"first_name": ..., "last_name": ..., "count": 5}) to find the person
2. Use execute("linkedin", "user", "get", {"user": "{alias from step 1}"}) to get their full profile
3. Use execute("linkedin", "email", "find", {"user": "{alias from step 1}"}) to get their email
4. Use execute("twitter", "user", "get", {"username": "..."}) to check their Twitter
Example 3: Adding v2 Features
Input:
Search for 50 marketing managers and filter by location.
Output:
1. Use execute("linkedin", "search", "search_users", {"title": "Marketing Manager", "count": 50}) to search
2. If more results exist, use get_page(cache_key="{cache_key}", offset=10, limit=10) to load additional pages
3. Use query_cache(cache_key="{cache_key}", conditions=[{"field": "location", "op": "contains", "value": "..."}]) to filter by location server-side
4. Use export_data(cache_key="{cache_key}", output_format="csv") to download the filtered list
Quick Reference: v2 Meta-Tools
| Tool | Purpose | When to use |
|---|---|---|
discover(source, category) |
Learn available endpoints and params | Before execute() when endpoint name or params are unknown |
execute(source, category, endpoint, params) |
Fetch data from any source | Every data retrieval — replaces all v1 tools |
get_page(cache_key, offset, limit) |
Load more items from previous execute() | When execute() returned next_offset |
query_cache(cache_key, conditions, sort_by, aggregate, group_by) |
Filter/sort/aggregate cached data | When you need to slice results without re-fetching |
export_data(cache_key, format) |
Save dataset as downloadable file | When user needs CSV/JSON/JSONL export |