MCP Server
Connect AI assistants like Claude, Cursor, and other MCP-compatible tools directly to Markidy. Search listings and profiles, send requests, create listings, and manage conversations from your AI client.
Setup
Connect any MCP-compatible AI assistant to Markidy. You will need an API key from your dashboard.
Option 1: NPX (stdio)
{
"mcpServers": {
"markidy": {
"command": "npx",
"args": ["-y", "@markidy/mcp-server"],
"env": {
"MARKIDY_API_KEY": "mk_your_api_key"
}
}
}
}Option 2: Streamable HTTP
{
"mcpServers": {
"markidy": {
"url": "https://api.markidy.com/api/mcp",
"headers": {
"Authorization": "Bearer mk_your_api_key"
}
}
}
}Core Tools
The most important tool for listing CRUD is get_category. Call it before create_listing or update_listing to discover:
- Which fields are
required - Which
acceptedValueFormatseach field accepts on write - How
GEO,MEDIA, and multi-valueURLvalues normalize into the canonicalvalueShape
list_categories ReadBrowse published categories and role keys.
get_category ReadGet category detail including roles, required fields, and value contracts for listing CRUD and meta filtering.
key string Category key such as jobs or mentoringsearch_listings ReadSearch listings by query, category, role, country, or searchable meta filters.
meta object? Use exact-match values for SELECT, _min/_max for NUMBER/DATE,
and _lat/_lng for GEO.get_listing ReadGet listing detail including profile.userId, meta fields, channel availability, and myRequest.
Use profile.userId with get_profile when you need the owner's full public profile.
create_listing WriteCreate a new listing. Plain fields stay as strings; complex fields may be sent as structured JSON objects/arrays or legacy JSON strings that match get_category.valueShape.
update_listing WriteUpdate listing field values or channels. Updating resets the listing to PENDING.
get_my_channels ReadCheck channel availability. markidy is built in for API-based messaging; Telegram and Discord are external contact channels.
geocode ReadConvert raw place text into coordinates for GEO search filters or GEO field payloads when you do not already have structured location data.
Field Contract Example
{
"category": {
"key": "jobs",
"roles": [
{
"key": "employer",
"fields": [
{
"key": "job-title",
"type": "SHORT_TEXT",
"required": true,
"displayTarget": "title",
"acceptsMultiple": false,
"acceptedValueFormats": ["plain-string"],
"valueEncoding": "plain-string",
"options": null
},
{
"key": "company-url",
"type": "URL",
"required": true,
"displayTarget": null,
"acceptsMultiple": true,
"acceptedValueFormats": ["json-string", "array", "plain-string"],
"valueEncoding": "json-string",
"valueShape": { "type": "array", "items": "string" },
"options": null
},
{
"key": "work-location",
"type": "GEO",
"required": true,
"displayTarget": null,
"acceptsMultiple": false,
"acceptedValueFormats": ["json-string", "object", "plain-string"],
"valueEncoding": "json-string",
"valueShape": {
"placeId": "string",
"name": "string",
"address": "string",
"lat": "number|null",
"lng": "number|null"
},
"options": null
}
]
}
]
}
}{
"categoryKey": "mentoring",
"roleKey": "mentor",
"meta": {
"headline": "Product mentor for early-stage founders",
"about-me": "<p>I help teams ship faster with better product decisions.</p>",
"format": "Remote",
"rate": "$50-$100 / hour"
},
"channels": ["markidy"]
}work-location = { "placeId": "...", "name": "Seoul", "address": "Seoul, South Korea", "lat": 37.5665, "lng": 126.9780 }, company-url = ["https://example.com"], portfolio = [{ "url": "https://cdn.example.com/image.jpg", "link": "https://example.com" }].
Legacy JSON strings are still accepted and normalized server-side.Usage Flows
Seeker Flow
list_categoriesBrowse categoriesgeocodeOptional: resolve raw place text for GEO filterssearch_listingsSearch listingsget_listingInspect detail, profile.userId, and channelsget_profileOptional: use listing.profile.userId for owner profile detailsend_match_requestSend requestlist_conversationsOpen chat after acceptanceProfile Contact Flow
search_profilesSearch candidates with sourcing filtersget_profileCheck recruitingPreferences, trustLinks, profileRequestPolicy, activeChannels, and myProfileRequestsend_profile_requestSend only when profileRequestPolicy.canRequest is trueget_my_requestsPoll with subjectType PROFILElist_conversationsContinue after acceptanceCreator Flow
get_my_channelsCheck channel availabilityget_categoryRead required fields and value formatscreate_listingCreate listingExample Conversation
User: Find me a mentor in Seoul who can help with product strategy
AI: I'll search Markidy for mentoring listings.
→ Calling search_listings(category: "mentoring", role: "mentor")
Found 3 results:
1. "Product mentor for early-stage founders" by Alex
2. "Career coach for PM interviews" by Jordan
3. "Growth mentor for indie hackers" by Sarah
User: Tell me more about the first one
AI: → Calling get_listing(id: "lst_...")
Alex — Product mentor for early-stage founders
Category: Mentoring → Mentor
Available channels: markidy, telegram
Format: Remote
Rate: $50-$100 / hour
Shall I send a match request?Listing detail includes profile.userId; call get_profile with that value when you need the owner's
full public profile before requesting.
Profile Tools
search_profiles ReadSearch verified public profiles with q, sort, country, hasCareer, openTo, roles, skills, seniority, workMode, availability, experience range, location, page, and pageSize. Default sort is relevance.
Enums: sort = relevance|trust|recent|posts; openTo = actively_looking|open_to_offers|not_looking|hiring_only; seniority = intern|junior|mid|senior|lead|executive; workMode = remote|hybrid|onsite|flexible; availability = immediately|one_month|three_months|not_specified.
roles and skills use the recruiting tag index for formatting variants such as Node.js, nodejs, and node; semantic aliases such as PM and Product Manager are not automatically expanded.
get_profile ReadGet public profile detail including socials, careers, activeChannels, recruitingPreferences, trustLinks, profileRequestPolicy, and myProfileRequest.
send_profile_request WriteSend a profile request with profileUserId, channels, and message.
get_incoming_profile_requests ReadList incoming requests on your profile with optional status, page, and pageSize.
Shared Request & Conversation Tools
The request and conversation surfaces are now subject-aware. Use subjectType to distinguish listing and profile flows, and profileUserId when narrowing to a specific public profile owner.
{
"tool": "get_my_requests",
"arguments": {
"subjectType": "PROFILE",
"status": "PENDING"
}
}
{
"tool": "list_conversations",
"arguments": {
"subjectType": "PROFILE"
}
}Authentication
All MCP tools use your API key for authentication. Generate one from your Dashboard.