Servers Changes Log Check Why How it works GitHub

Transparency log · MCP tool definitions

Every MCP server's tools, on the record.

Your AI client trusts the tool descriptions an MCP server sends it — and a server can change them after you approved it. HISTOR keeps a public, signed record of what every remote MCP server in the official registry advertised, and tells you the day it changed.

Remote endpoints: it lists tools and never calls one. Registry packages: bounded canary calls run inside the isolated sandbox. It never says a server is safe — it tells you what was said, and when.

DRAG TO ORBIT
SIM
—

WebGL is unavailable here. The picture is the log itself: each label is a leaf, leaf hashes climb a Merkle tree, and a signed tree head seals the root.

—
Registry endpoints
last crawl
—
Tool sets pinned
current
—
Changes
last 7 days
—
Labels in the log
all time
—
Last signed tree head
UTC

What HISTOR is for

Tool descriptions are instructions. They should not change behind your back.

The problem

A server can change what your model reads

When you connect an MCP server, its tool descriptions go straight to the model as instructions. A server can pass your review with harmless descriptions and change them next week — one added sentence is all a prompt injection needs, and most clients never ask you again.

What HISTOR does

It keeps the public record

Every day HISTOR reads what each remote (streamable-HTTP) endpoint in the official MCP registry advertises, fingerprints it, signs what it saw and appends it to a log that can only grow. When a server's definitions change, the change gets a date and a diff.

What you get

A second pair of eyes you can check

Look up any server before you trust it. Paste what your client received and learn whether everyone else sees the same thing. Follow changes in a feed, or put a badge in your README. Every answer is signed, so you can verify it instead of believing it.

Who it is for

People who use MCP serversin Claude, Cursor or any client — check a server before you connect it, and again when it changes.
Agent builderswhose agents connect to servers on their own — call /check before trusting a tool set.
Registries and directoriesthat want more than stars and download counts — show when a listing's tools last changed.
Server authorswho want to show a stable, documented history — add the badge, and every change you ship is dated in public.

Four words used on this page

Tool definitions
The name, description and input schema of each tool a server offers — the text your model reads.
Pinned
HISTOR has recorded a fingerprint (digest) of the exact definitions it saw, so any later change is detectable.
Label
One signed statement about one observation: what was seen, what matched, whether it changed. Anyone can verify it offline.
Signed tree head
The log's signed summary after each crawl. Comparing two of them proves nothing was deleted or rewritten in between.

GigHQ.ai

ai.gighq/gighq · https://mcp.gighq.ai/mcp

Job-search tracker for AI agents: applications, stale follow-ups, skills gaps, H-1B lookup.

First observed
2026-10-23
Unchanged since
2026-10-23
Last observed
2026-10-23
Observations
1
Changes on record
Tools
34

Tool definitions as last observed (34)

  • add_career_entry — Saves a new career journal entry to the user's GigHQ profile. Use this to document professional achievements, projects, skills acquired, or reflections tied to a specific role. Entry types: 1 = achievement — a concrete win, result, or impact (default) 2 = project — a specific initiative the user owned or contributed to 3 = skill_acquired — a new skill, tool, or capability gained 4 = refle …
  • add_contact_interaction — Logs a touchpoint with one of the user's job-search contacts — a call, a LinkedIn message, a coffee chat, a referral conversation, etc. The entry appears in the contact's interaction timeline in GigHQ. **type is required.** Infer the best-fit type from what happened: • text_message — SMS/text • email_external — email • call — phone or video call • linkedin_connection_request — sent or acc …
  • add_job_application_note — Adds a note to a job application's timeline. Use this to log any touchpoint or interaction — a call, a LinkedIn message, a referral conversation, a networking event, etc. **category is required.** Infer the best-fit category from the note content before calling. Use this mapping: • text_message — contact via SMS/text • email_external — contact via email • call — phone or video call • link …
  • check_stale_applications — Returns job applications that haven't had a status update in a configurable number of days, along with a suggested follow-up action for each. Useful for surfacing applications the user may have forgotten about.
  • create_job_application — Creates a new job application entry in GigHQ, or reuses an existing active one for the same company+job if the backend finds one — check `alreadyExist` in the response. Calling find_job_application first is still recommended when you want to inspect a possible match before deciding. New applications always start in PROSPECTING status — there is no way to create directly into APPLIED/INTERVIEWING/ …
  • delete_career_entry — Permanently deletes a career journal entry by UUID. This action cannot be undone — confirm with the user before calling. Use list_career_entries to find the UUID if you don't have it.
  • delete_job_application_note — Permanently deletes a note from a job application's timeline. This action cannot be undone — confirm with the user before calling. Use list_job_application_notes to find the note UUID if you don't have it.
  • find_job_application — Checks whether the user already has a saved job application for a SPECIFIC posting — call this before create_job_application to avoid creating a duplicate. Matches BOTH company name and job title (case-insensitive substring on each), so it can tell two different roles at the same company apart. search_job_applications cannot do this — it only filters by company/status/isActive, not job title. Bot …
  • generate_career_compass — Runs GigHQ's CareerCompass AI pipeline against the user's resume data to generate 3 candidate professional objective statements, a positioning statement, categorized skills, and a suggested target market (industries, company sizes, geographic locations). This is an EXPENSIVE, one-time 'career strategy' action (4 parallel AI completions server-side) — not a cheap or repeatable lookup. Prefer get_ca …
  • get_career_compass — Retrieves the user's saved CareerCompass data: professional objectives, positioning statement, categorized skills (technical/soft/management/other), and target market (industries, company size, geographic location). Cheap read — prefer this over generate_career_compass whenever the user just wants to review what's already saved.
  • get_career_journal_prompts — Returns a set of context-aware reflection questions to guide a career journaling session. Use this at the start of any journaling conversation to orient the discussion. The tool reads the user's GigHQ experience records and existing career entries to tailor the questions — surfacing the most relevant role, estimating tenure, and flagging roles with sparse documentation. Session types: achievem …
  • get_company_details — Get detailed information about a company (applicants by status, Community Signal, H1B sponsorship status, employee count, website, etc.) using its UUID. The metrics window defaults to the last 30 days. Optional startDate and endDate parameters support other date ranges. Returns GigHQ's recorded company data and community metrics for the selected window.
  • get_contact — Returns full details for one of the user's job-search contacts: profile info, outreach status, linked job applications, and the complete interaction history (calls, LinkedIn messages, coffee chats, etc.). Use this before drafting outreach or follow-up messages so the message reflects what has already been said, and before interviews to remind the user who they know at the company. Find the UUID w …
  • get_job_application — Fetches the full details of a single job application by its UUID — status history, correspondence dates, job description, and related metadata. Do NOT use this tool when the user asks about notes ("do I have any notes", "show me my notes", "list notes"). Use list_job_application_notes for that. Tip: if you only have a company name, call search_job_applications first to get the UUID.
  • get_job_details — Get detailed community metrics for a specific job listing (applicants by status, average days per status, Community Signal) using its UUID. The metrics window defaults to the last 30 days. When the user requests a longer period — e.g. "last 6 months", "last year", "since January" — compute startDate and endDate from that phrase and pass them explicitly.
  • get_job_fit_evidence — Retrieves a saved GigHQ job application, candidate profile data, and the most relevant Career Journal evidence for assessing role fit. Career evidence is ranked by job keywords, competency coverage, evidence quality, recency, and diversity; the default is 20 entries, grouped by competency bucket (career_journal.competency_rollup) to make coverage and gaps easy to spot. This read-only tool supplies …
  • get_recent_applications — Retrieves a summary of the user's 10 most recent job applications, including status, company name, and correspondence dates. `totalCount` in the response reflects the full number of applications, not just the 10 returned — mention it if it's larger than the list shown, and point the user to search_job_applications for the rest.
  • list_career_entries — Returns the user's career journal entries from GigHQ, newest first. Supports optional filtering by entry type and date range. Use this tool to: - Review what the user has already documented before starting a journaling session - Find entries to update or refine - Identify gaps (roles with few or no entries) - Synthesise entries into resume bullets or interview stories Entry type filter v …
  • list_experiences — Returns the user's work experience records with their integer IDs. Use this tool BEFORE calling `add_career_entry` or `update_career_entry` to find the correct `experience_id` for the role the entry belongs to. Present the role list to the user and confirm which one they mean before saving. This is the tool-based alternative to the `gighq://experience` resource and works in all contexts includin …
  • list_job_application_notes — Use this tool when the user asks about notes on a job application — "do I have any notes", "show me my notes", "what notes do I have", etc. Returns all user-authored notes for a job application ordered by date, including UUID, body text, category, and timestamp. Use the returned UUIDs in follow-up update_job_application_note or delete_job_application_note calls.
  • lookup_h1b_sponsorship — Looks up a company by name and returns GigHQ's recorded H1B sponsorship and concurrent H1B flags. Returns unknown when a flag is unavailable. These results describe the data recorded in GigHQ.
  • prepare_for_interview — Assembles everything needed to prepare for an interview on a saved GigHQ job application: the job and company context, the candidate's full profile, their Career Journal grouped by role (for STAR/CAR story material), which evidence best matches the role (to emphasize) and which competencies are weakly covered (to address or reframe), and a company briefing (Community Signal, H1B status, size). Thi …
  • recommend_target_roles — Assembles the user's profile, experience, career journal evidence (with a broad competency rollup), and saved CareerCompass data (if any) for recommending role titles to target. This is the inverse of get_job_fit_evidence: instead of evaluating fit for one specific job, it starts from the candidate's profile. Role taxonomy only — it does NOT validate recommendations against live job-market demand …
  • save_career_compass — Persists CareerCompass data to the user's GigHQ profile. This REPLACES the full saved record — any array field you omit (technical_skills, soft_skills, management_skills, target_industries, company_size, geographic_location, other_skills) is saved as empty, not left unchanged. Call get_career_compass first and pass through every field the user isn't changing. Only call this after the user has revi …
  • search_companies — Search for companies by name to retrieve their unique identifiers (UUIDs).
  • search_contacts — Searches the user's job-search contacts in GigHQ — recruiters, hiring managers, referrals, and other people they are networking with. Use this tool to: - Find a contact before drafting an outreach or follow-up message - See who the user already knows at a company before an interview or application - Review which contacts are stuck at a given outreach stage Status filter values: not_contact …
  • search_job_applications — Search the user's job applications by company name, status, or both. Use this when the user asks about a specific company's application, wants to find a particular application to view or update its status, or wants to know how many applications are in a given status (e.g. "how many applications are in Prospecting?"). Omit `company` to search across all companies — required when the request is sta …
  • toggle_job_application_interest — Use this tool when the user says "not interested", "no longer interested", "withdraw interest", "I'm out", "remove from pipeline", or any equivalent phrase. This is the ONLY correct tool for withdrawing interest — do not use update_job_application_status as a proxy. Deactivates an active application (or reactivates a previously deactivated one). Mirrors the "I am no longer interested in this role …
  • update_career_entry — Updates an existing career journal entry. Only the fields provided will be changed — all other fields remain as-is. Use this to refine descriptions, add missing numbers to the metrics field, correct the entry date, or re-type an entry. This is the right tool to backfill quantification on entries saved without a full three-number breakdown (scale of action, direct result, organizational impact).
  • update_contact_status — Updates a contact's outreach status in GigHQ. A status-change entry is automatically logged in the contact's interaction history. Status progression: not_contacted → reached_out → responded → in_conversation → connected. Use 'cold' when the thread has gone quiet. Find the contact's UUID with `search_contacts`.
  • update_job_application — Enriches or corrects an existing job application's saved posting details: source URL and/or job description. Use this when the user finds the JD later, wants to add the posting link, or wants to correct the saved description. Do NOT use this for status changes — use update_job_application_status. Do NOT use this for withdraw/reactivate ('not interested') — use toggle_job_application_interest. Thi …
  • update_job_application_note — Updates the body or category of an existing job application note. Both body and category are required — the backend replaces the full note on update. If the user only mentions updating the body and doesn't specify a category, infer the best-fit category from the note content using this mapping: • text_message — contact via SMS/text • email_external — contact via email • call — phone or vide …
  • update_job_application_status — STOP — if the user says "not interested", "no longer interested", "withdraw interest", "remove from pipeline", or any equivalent: do NOT call this tool. Call toggle_job_application_interest instead. There is no "not interested" status here; attempting to use REJECTED or any other status as a proxy is wrong. Updates the status of a job application by its UUID to one of the supported pipeline stage …
  • weekly_job_search_summary — Generates a weekly job search health summary. Aggregates up to 30 active applications and surfaces status distribution, conversion rates, longest-open applications, pipeline clustering insights, and a suggested focus area for the coming week.

The signed observations, every earlier tool set and a diff of each change: this page with scripts on, or /api/v1/servers/c3bd0f33b69fe924.

Read → digest → label → append → sign → compare

How the log works

Six steps, every one of them checkable by someone who does not trust HISTOR. The only thing you have to take on faith is that the observation happened when the label says it did — and the log makes it impossible to change that story afterwards.

01

Read

Remote endpoints in the official MCP registry: initialize, then tools/list, drained across every page; no tool is called, and private addresses are refused before the connection opens. npm and PyPI packages: installed and started in the sandbox described below, with no route out.

02

Digest

The tool set is reduced to name, description, input and output schema, sorted by UTF-16 code units and hashed over its RFC 8785 canonical form. Anyone holding the same tools gets the same digest — which is what makes a comparison possible.

03

Label

Four MTL/1 methods, one signed AWR/2 document each: what was observed, what the WARDEN pattern set matched, whether the definitions changed since the last label, and whether the name is on a threat list. No score, ever.

04

Append

Every label becomes a leaf of an RFC 9162 Merkle tree: leaf hash = SHA-256(0x00 ‖ JCS(label)). The label you download is the leaf input, so you can recompute its hash yourself.

05

Sign

After each crawl HISTOR signs a tree head: the size and the root. Keep yesterday's head; ask for a consistency proof to today's; if anything was removed or rewritten, the proof fails.

06

Compare

Each day a continuity label compares the new digest with the last one. Equal: "unchanged since". Different: a change, with the date and a per-tool diff. A client that checks what it received adds the view no crawler has.

Where an npm or PyPI package is run

Test conditions

A package observation is true for these conditions, and no others. Every package page names the exact image it ran in and any configuration it was given.

System

Linux x86_64, inside gVisor (runsc): the package talks to a kernel written for sandboxing, not to the host's. An unprivileged user, no capabilities, a read-only root.

Runtimes

npm packages in histor-node:22, PyPI packages in histor-python:3.12: the official node:22-bookworm-slim and python:3.12-slim images plus bash, git, Python 3 or Node 22 and a Java 21 runtime — never Docker — built when a sandbox host is installed. A package whose Requires-Python excludes 3.12 runs on histor-python:3.13 or 3.14; one that requires a newer Node runs again on histor-node:24. The exact image a package ran in is on its page.

Install

npm with --ignore-scripts, then the install scripts in a traced stage of their own. PyPI: wheels only — a package that ships only source is reported, never built.

Network

No route out. Every name the package looks up resolves to HISTOR's own traps, which record what was sent and forward nothing. A server that needs the internet to start shows that here.

Secrets

None are real. Decoy credentials sit in HOME and a decoy .env in the working directory. A variable the package says it needs gets a placeholder; where the placeholder was sent is recorded.

Limits

512 MB of memory, one CPU, 64 MB of /tmp. 360 s to install, 150 s to start and answer; up to 15 tools called once each with canary arguments, 8 s per call.

Configuration

Only names: required variables its registry entry declares or that it printed when it exited, and a start argument such as serve when its usage text offers one. Never a value from anyone else.

What a label does not say

The profile HISTOR implements forbids the words safe, secure, audited, certified, approved and trusted. Here is why, in the terms of what the log can and cannot show.

Not a safety rating

A pattern match is a reason to read a definition, not a finding. Three of the four methods can never return fail. There is no score to rank by, because no score HISTOR could compute would mean what a reader takes it to mean.

Not the code

Labels are about advertised text. A remote endpoint's source is never read and its tools are never invoked; a package runs only in the sandbox, against nothing real. A server can keep identical definitions and behave differently for real users; the log cannot see that, and says so inside every label.

A change is not an accusation

A version bump changes definitions too. A change is shown as a date and a diff, in amber, never red. What you do with it is yours: re-read, re-approve, or pin the old digest.

A package as run here, not on your machine

An npm or PyPI server is observed under the test conditions above: Linux, no internet, placeholder keys. One that needs Windows, a real account or the network may show fewer tools or none; its page says why it exited.

One operator, one key

Today one party runs the log. A second observer on another network is the next step, and any AIMarket hub can run one. Until then, what the key proves is who said it — not that it is true.

Behind a login, unseen

Endpoints that require authentication answer 401 to everyone without a key, including HISTOR. They are counted and listed as not observed, never dropped from the numbers.

For clients, registries and server authors

Use it

Before your agent trusts a server, send the tools it received. The answer is signed by the log's did:key and names the tree head it was given under.

curl -sS https://histor.modelmarket.dev/api/v1/check \
  -H 'Content-Type: application/json' \
  -d '{"endpoint":"https://example.com/mcp","tools":[ …tools/list result… ],"contribute":true}'
# -> {"type":"histor.check/v1","match":"same"|"different"|"previously-observed"|…,
#     "observed":{"unchangedSince":"…","changes":0}, "patternScan":{…}, "signature":{…}}

# README badge for your server
[![MCP tool defs](https://histor.modelmarket.dev/badge/<id>.svg)](https://histor.modelmarket.dev/s/<id>)

# Atom feed of every observed change
https://histor.modelmarket.dev/feed.xml
WARDENchecks definitions at connect
HISTORremembers what was advertised
THEMISadmits at publish
Hublists histor.check@v1
AWRthe signed format

Questions

Is this a marketplace listing?

No. The server list is the log's index: every remote endpoint in the official MCP registry, with what HISTOR could observe about it. Nothing here is for sale and nothing is ranked by quality.

Does HISTOR tell me a server is safe?

No, and it never will. It tells you what a server advertised, whether that changed, and which published patterns matched the text. Whether to trust the server is your decision — HISTOR makes sure you decide on the same facts as everyone else.

Why are so many servers "not observed"?

Most remote MCP endpoints require a login (they answer 401 to anyone without a key), some use the legacy SSE transport or need per-user values in the URL, and some are simply down. They stay on the list with the reason, so the numbers never hide them.

How do I check a server I already use?

Open the Check tab, paste the server's endpoint and the tools/list result your client received, and press Check. You get back, signed, whether HISTOR observed the same definitions — or different ones, or an older set.

How do I get a badge for my server?

Find your endpoint on the Servers tab, open it, and copy the Markdown snippet under the facts. The badge shows the date your definitions were pinned or last changed, and links to the full history.

Why should I trust HISTOR itself?

You do not have to. Every label and every tree head is signed with one published key; the Log tab proves in your browser that the log only grew; and the command-line auditor does the same from any machine. What remains is that one operator runs it today — a second, independent observer is the next step.

What does it cost?

Looking things up, the badges, the feed and /check are free. HISTOR also offers histor.check@v1 to the AIMarket Hub, so agents can reach it through the market.

I run an MCP server. What does HISTOR send it, and how do I opt out?

Once a day: initialize, notifications/initialized and tools/list — never a tool call, never a redirect followed, at most two connections per host, from a User-Agent that starts with histor/. To be left out, open an issue on the histor repository with your endpoint or host; it is then listed as not observed (operator-opt-out), with the reason, rather than silently dropped. Labels already in the log stay: the log only grows.