Koskamo

Zovo Typing Test MCP

Enables agents to conduct live typing speed tests within chat interfaces, measuring WPM, accuracy, and consistency. Supports timed tests of various durations, multiple passage styles including code, and custom text input. Provides detailed scoring, weak-key drills, and shareable result cards.

Endpoint and access

No sign-in to connect and list tools. Individual tools may still need a vendor account, credentials, or permissions; check the documented prerequisites.

Zovo Typing Test MCP logo, by ZovoCommunity listingStreamable HTTPNo sign-inEndpoint checked 2026-11-01Published by Zovo
MCP endpoint (Streamable HTTP)
https://typing-test.zovo.one/mcp
Vendor documentation

What you can do with it

  • Run a 60-second typing test with sentences and punctuation
  • Test typing speed on a custom paragraph pasted by the user
  • Generate a weak-key practice drill based on test results
  • Create a shareable challenge link for a specific typing passage

Source and maintenance

Community listingRegistry 1.0.1

Protocol and capabilities

Server
typing-test 1.0.1
MCP protocol
2025-06-18
Tools
2 advertised
Resources
1 advertised
Resource templates
1 advertised
Prompts
Not advertised
Server-advertised capabilities
{
  "tools": {
    "listChanged": true
  },
  "resources": {
    "listChanged": true
  }
}

Server-provided instructions

Untrusted server output shown for inspection. It is not Koskamo guidance and is excluded from knowledge search.

Zovo Typing Test runs a live typing speed test in the chat. Call show_typing_test to start a test (the widget times it and submits the result). Call calculate_typing_score only to score text the user already typed (target text, typed text, seconds). WPM = (correct characters / 5) / minutes.

Tools

2 advertised

calculate_typing_score — Calculate typing score
Advertised by the server during the last successful anonymous check.
Advertised read-only

Use this when a typing test has finished, or when the user gives the target passage, what they typed, and the time taken and wants their typing speed. Compares word by word and computes exact WPM = (correct characters / 5) / minutes, raw WPM (all typed characters), accuracy = correct / (correct + errors), errors (incorrect + extra + skipped letters), consistency and per-second speed (when samples are given), and the weakest keys. Returns a shareable result card (SVG) and a challenge link. Does not run a test or time anything itself; seconds must be between 1 and 3600. Do not use for reading speed or word counts.

calculate_typing_score input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "target_text",
    "typed_text",
    "seconds"
  ],
  "properties": {
    "mode": {
      "enum": [
        "timed",
        "passage"
      ],
      "type": "string",
      "description": "Settings of the test from show_typing_test, used to label the result and build a challenge link. Example: timed."
    },
    "seed": {
      "type": "integer",
      "maximum": 2147483647,
      "minimum": 1,
      "description": "Seed from show_typing_test, e.g. 4821, so a challenge link reproduces the same passage."
    },
    "samples": {
      "type": "array",
      "items": {
        "type": "integer",
        "maximum": 9007199254740991,
        "minimum": 0
      },
      "maxItems": 3600,
      "description": "Optional, sent by the widget: cumulative count of characters entered at the end of each whole second, e.g. [5, 11, 16]. Used for per-second speed and consistency."
    },
    "seconds": {
      "type": "number",
      "description": "Elapsed typing time in seconds, from the first keystroke to the end (the full duration for a timed test), e.g. 60. Must be between 1 and 3600."
    },
    "difficulty": {
      "enum": [
        "words",
        "sentences",
        "numbers",
        "code"
      ],
      "type": "string",
      "description": "Difficulty from show_typing_test, e.g. words."
    },
    "focus_keys": {
      "type": "string",
      "maxLength": 40,
      "description": "Drill keys from show_typing_test, e.g. 'eth'."
    },
    "typed_text": {
      "type": "string",
      "maxLength": 20000,
      "description": "Exactly what the user typed, including mistakes, e.g. 'the quikc brown fox'. May be empty."
    },
    "custom_text": {
      "type": "string",
      "maxLength": 20000,
      "description": "Sent by the widget for custom-text tests: the full custom text from show_typing_test, e.g. 'The early bird catches the worm.', so the challenge link reproduces the whole passage. Omit otherwise."
    },
    "missed_keys": {
      "type": "string",
      "maxLength": 4000,
      "description": "Optional, sent by the widget: one character per mistyped keystroke, giving the key that was expected (including mistakes later corrected), e.g. 'eet'. Used to find weak keys."
    },
    "target_text": {
      "type": "string",
      "maxLength": 20000,
      "minLength": 1,
      "description": "The passage the user was asked to type, exactly as shown, e.g. 'the quick brown fox'."
    },
    "duration_seconds": {
      "type": "integer",
      "maximum": 600,
      "minimum": 10,
      "description": "Timed-test length from show_typing_test, e.g. 60."
    }
  }
}
calculate_typing_score output schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "kind",
    "summary",
    "wpm",
    "raw_wpm",
    "accuracy",
    "correct_chars",
    "incorrect_chars",
    "extra_chars",
    "missed_chars",
    "untyped_chars",
    "typed_chars",
    "target_chars",
    "errors",
    "seconds",
    "completed",
    "consistency",
    "per_second_wpm",
    "weak_keys",
    "label",
    "settings",
    "downloads"
  ],
  "properties": {
    "wpm": {
      "type": "number"
    },
    "kind": {
      "type": "string"
    },
    "label": {
      "type": "string"
    },
    "errors": {
      "type": "number"
    },
    "raw_wpm": {
      "type": "number"
    },
    "seconds": {
      "type": "number"
    },
    "summary": {
      "type": "string"
    },
    "accuracy": {
      "type": "number"
    },
    "settings": {
      "type": "object",
      "propertyNames": {
        "type": "string"
      },
      "additionalProperties": {}
    },
    "completed": {
      "type": "boolean"
    },
    "downloads": {
      "type": "object",
      "required": [
        "card",
        "challenge"
      ],
      "properties": {
        "card": {
          "type": "string"
        },
        "challenge": {
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "weak_keys": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "key",
          "misses"
        ],
        "properties": {
          "key": {
            "type": "string"
          },
          "misses": {
            "type": "number"
          }
        },
        "additionalProperties": false
      }
    },
    "consistency": {
      "type": [
        "number",
        "null"
      ]
    },
    "extra_chars": {
      "type": "number"
    },
    "typed_chars": {
      "type": "number"
    },
    "missed_chars": {
      "type": "number"
    },
    "target_chars": {
      "type": "number"
    },
    "correct_chars": {
      "type": "number"
    },
    "untyped_chars": {
      "type": "number"
    },
    "per_second_wpm": {
      "type": "array",
      "items": {
        "type": "number"
      }
    },
    "incorrect_chars": {
      "type": "number"
    }
  },
  "additionalProperties": false
}
calculate_typing_score annotations
{
  "title": "Calculate typing score",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
show_typing_test — Show typing test
Advertised by the server during the last successful anonymous check.
Advertised read-only

Use this when the user wants to take a typing test, check their typing speed (WPM), practice typing, test on their own paragraph, or drill weak keys. Opens a live test in the widget: the timer starts on the first keystroke, characters are highlighted as typed, and the widget scores the result with calculate_typing_score. Returns the passage settings and a challenge link that opens the same test in a browser. Does not score text by itself and does not save results between conversations. Do not use for counting words in a document or for typing tutorials without a test.

show_typing_test input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "properties": {
    "mode": {
      "enum": [
        "timed",
        "passage"
      ],
      "type": "string",
      "description": "timed (type until the clock runs out) or passage (type one full passage; time stops at the last character). Defaults to timed, or passage when custom_text is given. Example: timed."
    },
    "seed": {
      "type": "integer",
      "maximum": 2147483647,
      "minimum": 1,
      "description": "Optional number that picks the passage; the same seed and settings give the same passage (for retakes and fair challenges). Example: 4821."
    },
    "difficulty": {
      "enum": [
        "words",
        "sentences",
        "numbers",
        "code"
      ],
      "type": "string",
      "description": "Passage style: words (common English words, no punctuation), sentences (prose with capitals and punctuation), numbers (words mixed with numbers, times and dates), code (short code snippets with line breaks). Default words. Example: sentences."
    },
    "focus_keys": {
      "type": "string",
      "maxLength": 40,
      "description": "Practice drill: the keys to train, e.g. 'eth' or 'q;7' (a list like 'q, z and x' also works). Builds a drill passage from words that use these keys. Usually the weak_keys from a previous result."
    },
    "custom_text": {
      "type": "string",
      "maxLength": 20000,
      "description": "Text the user wants to be tested on, pasted verbatim, e.g. 'The early bird catches the worm.' Curly quotes and dashes become keyboard characters; whitespace is collapsed (line breaks are kept when difficulty is code). At least 5 characters; text beyond 3,000 characters is cut at a word boundary."
    },
    "duration_seconds": {
      "type": "integer",
      "maximum": 600,
      "minimum": 10,
      "description": "Length of a timed test in seconds, 10-600. Common choices are 15, 30, 60, 120; job tests often use 60, 180 or 300. Default 60. Example: 60."
    }
  }
}
show_typing_test output schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "kind",
    "title",
    "mode",
    "duration_seconds",
    "difficulty",
    "difficulty_label",
    "seed",
    "focus_keys",
    "custom",
    "char_count",
    "word_count",
    "text",
    "text_preview",
    "downloads"
  ],
  "properties": {
    "kind": {
      "type": "string"
    },
    "mode": {
      "type": "string"
    },
    "seed": {
      "type": "number"
    },
    "text": {
      "type": [
        "string",
        "null"
      ]
    },
    "title": {
      "type": "string"
    },
    "custom": {
      "type": "boolean"
    },
    "downloads": {
      "type": "object",
      "required": [
        "challenge"
      ],
      "properties": {
        "challenge": {
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "char_count": {
      "type": "number"
    },
    "difficulty": {
      "type": "string"
    },
    "focus_keys": {
      "type": [
        "string",
        "null"
      ]
    },
    "word_count": {
      "type": "number"
    },
    "text_preview": {
      "type": "string"
    },
    "difficulty_label": {
      "type": "string"
    },
    "duration_seconds": {
      "type": "number"
    }
  },
  "additionalProperties": false
}
show_typing_test annotations
{
  "title": "Show typing test",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}

Prompts

Not advertised

No prompt definitions available.

Resources

1 advertised

typing-test-widget — Zovo Typing Test view

Advertised by the server during the last successful anonymous check.

Interactive view for Zovo Typing Test.

typing-test-widget URI
ui://widget/typing-test-v3-1.0.1-210e82306b2aeb9621cdff9a9e56dce0440805904efd47b771d9c6921749a852.html

MIME type: text/html;profile=mcp-app

typing-test-widget-legacy — Zovo Typing Test view (previous versions)

Advertised by the server during the last successful anonymous check.

typing-test-widget-legacy URI template
ui://widget/typing-test-{version}.html

MIME type: text/html;profile=mcp-app

30-day availability

Aggregated from read-only remote checks; this is not a tool-execution or security guarantee.

Successful checks
1 of 1 (100%)
Average latency
527 ms
95th percentile latency
527 ms

Maintenance history

Public check and source-refresh events. Editorial and ownership records remain private.

  • · probe · passed · 527 ms · metadata changed · 2 tool(s), 1 resource(s), 1 resource template(s)

Connect from your client

Each snippet registers the same endpoint; pick the client you use.

This server is operated by the named third party. Listing and endpoint checks are not an endorsement or a security audit. Review the operator's permissions, terms, and data handling before connecting. How listings are checked and corrected.

Claude Code

Run this once in a terminal. It registers the remote server. Use --scope project to write .mcp.json for the repo.
Claude Code configuration
claude mcp add --transport http zovo-typing-test-mcp https://typing-test.zovo.one/mcp

Codex

Run this once. Codex stores MCP servers in ~/.codex/config.toml (or .codex/config.toml in a trusted project).
Codex configuration
codex mcp add zovo-typing-test-mcp --url https://typing-test.zovo.one/mcp

Cursor

Merge this server into .cursor/mcp.json in your project, then enable zovo-typing-test-mcp in your MCP settings.
Cursor configuration
{
  "mcpServers": {
    "zovo-typing-test-mcp": {
      "url": "https://typing-test.zovo.one/mcp"
    }
  }
}

Cline

Merge this into cline_mcp_settings.json (Cline → MCP Servers → Configure).
Cline configuration
{
  "mcpServers": {
    "zovo-typing-test-mcp": {
      "type": "streamableHttp",
      "url": "https://typing-test.zovo.one/mcp",
      "disabled": false
    }
  }
}

VS Code

Merge this server into .vscode/mcp.json. Use MCP: List Servers to start zovo-typing-test-mcp and inspect its tools.
VS Code configuration
{
  "servers": {
    "zovo-typing-test-mcp": {
      "type": "http",
      "url": "https://typing-test.zovo.one/mcp"
    }
  }
}

Gemini CLI

Run this once. It writes .gemini/settings.json in the current project; pass --scope user for ~/.gemini/settings.json.
Gemini CLI configuration
gemini mcp add --transport http zovo-typing-test-mcp https://typing-test.zovo.one/mcp

Claude Desktop

Merge this into claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/, Windows: %APPDATA%\Claude\), then restart Claude Desktop.
Claude Desktop configuration
{
  "mcpServers": {
    "zovo-typing-test-mcp": {
      "url": "https://typing-test.zovo.one/mcp"
    }
  }
}

Windsurf

Merge this into ~/.codeium/windsurf/mcp_config.json, then refresh MCP in Cascade. Windsurf remote servers use serverUrl, not url.
Windsurf configuration
{
  "mcpServers": {
    "zovo-typing-test-mcp": {
      "serverUrl": "https://typing-test.zovo.one/mcp"
    }
  }
}

Let your agent find its tools

Find servers like Zovo Typing Test MCP from your agent. Add Koskamo once to search the index for endpoints, access requirements, and client setup. Public discovery needs no key.