JobCrawls
Server Details
Search jobs in Finland and calculate net salary. Read-only, no login. English, Finnish, Swedish.
- Status
- Healthy
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-11-25
- URL
TDQS
Scored across 4 tools
Each tool targets a completely distinct operation: searching jobs, retrieving a single job's details, listing filter facets, and calculating net salary. There is no overlap or ambiguity between them.
All tool names follow a consistent snake_case verb_noun pattern: search_jobs, get_job_details, list_job_filters, calculate_net_salary_finland. The inclusion of 'finland' in the salary tool is descriptive, not a break in convention.
Four tools perfectly match the server's scope: search, filter discovery, detail retrieval, and a standalone salary calculator. No tool feels redundant or missing; the set is lean and purposeful.
The core job-search lifecycle is fully covered: search jobs, discover available filters, and fetch full details for a listing. The salary calculator addresses a common adjacent user need, and no obvious gaps exist for an aggregator.
Available Tools
4 toolscalculate_net_salary_finlandCalculate net salary in Finland (gross to net, employer cost)ARead-onlyIdempotentInspect
Gross-to-net salary calculator for Finland, from the JobCrawls tax iceberg calculator. Use for questions like "what is 4000 gross net in Finland", "paljonko jää käteen 4200 euron bruttopalkasta Helsingissä", or "vad blir nettolönen på 3800 brutto i Helsingfors". Give a gross salary (EUR per month by default, or per year), or a target net to get the gross it takes, and optionally the municipality, employer size, age, dependent children, commuting costs and investment income. It does not accept church membership or union fees. The linked page comes back in the language detected from "municipality" when locale is omitted, else English; pass locale explicitly to override. Returns monthly and annual breakdowns: employee pension and unemployment contributions, state, municipal, church and Yle taxes, net pay, employer contributions and the true cost of employment, plus the effective tax rate, the assumptions used and a link to the same scenario on jobcrawls.com. Uses the current tax year's official Finnish parameters; an estimate, not tax advice.
| Name | Required | Description | Default |
|---|---|---|---|
| age | No | Age in years, affects pension and unemployment contributions. | |
| net | No | Target net pay in euros (same period): the tool solves the gross salary that leaves this in hand. Give either gross or net. | |
| gross | No | Gross salary in euros, per month unless period is "year". Give either gross or net. | |
| locale | No | Set this to the language of the user's message (fi for Finnish, sv for Swedish, en for English or any other language), even when the job titles or place names in it are English. Language of the result notes, the inline card and the linked page. When omitted, detected from "municipality" if it is given in Finnish or Swedish form; otherwise defaults to en. | |
| period | No | Period of every money amount given. Default month. | |
| dividends | No | Listed-company dividends in the same period (capital income). | |
| includeVat | No | Also subtract the VAT paid when the net is spent (an estimate). Default false. | |
| capitalGains | No | Capital gains net of acquisition cost in the same period. | |
| employerSize | No | Employer payroll size for the unemployment-insurance rate (large = payroll above about EUR 2.5 million). Omit for a blended average. | |
| municipality | No | Finnish municipality name, e.g. "Helsinki" or "Espoo". Omit for the national-average municipal tax rate. | |
| commutingCosts | No | Commuting costs in the same period; deductible above the own-liability share, capped. | |
| isSoleGuardian | No | Single parent with dependent children (child deduction). | |
| dependentChildren | No | Number of dependent children, affects the child tax deduction. | |
| unlistedDividends | No | Dividends from the person's own unlisted company in the same period (8% yield rule). | |
| unlistedNetAssets | No | Mathematical value of the person's shares in that company, EUR (a stock, not per period). |
Output Schema
| Name | Required | Description |
|---|---|---|
| input | Yes | The inputs the calculation used, after defaults. |
| rates | Yes | |
| annual | Yes | Breakdown per year, EUR. |
| locale | Yes | |
| method | Yes | |
| monthly | Yes | Breakdown per month, EUR. |
| pageUrl | Yes | The same scenario on jobcrawls.com, where church tax and union fees can be set privately. |
| taxYear | Yes | |
| currency | Yes | |
| assumptions | Yes | |
| investments | Yes | Capital income breakdown, or null when no investment income was given. |
| destinations | Yes | Where the taxes and contributions go, EUR per year. |
| icebergSvgUrl | Yes | Image illustrating the breakdown. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish the read-only idempotent safety profile, and the description adds substantial context beyond them: locale detection rules, the returned breakdown fields, the current-tax-year basis, and an explicit 'estimate, not tax advice' caveat.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single dense paragraph, but front-loaded with purpose and examples, and nearly every sentence carries distinct information (inputs, exclusions, locale, returns, caveat). Slightly heavy, yet nothing is padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 15-parameter zero-required calculator with an output schema, the description covers inputs, edge cases (locale/municipality interplay), output shape, and limitations. Since an output schema exists, the return-value prose is bonus rather than a gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds cross-parameter meaning the schema cannot: the gross-vs-net mutual-exclusion intent, the period default, and the interaction where municipality's language form drives locale detection. It adds real value on top of a fully documented schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Gross-to-net salary calculator for Finland') plus the domain context (JobCrawls tax iceberg calculator). It is trivially distinguishable from the job-search siblings, which share no overlap.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete example questions in three languages, explains the gross-or-net input modes, enumerates the optional dimensions, and states explicit exclusions ('does not accept church membership or union fees'). An agent knows exactly when and how to call it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_job_detailsGet full job listing detailsARead-onlyIdempotentInspect
Fetch the complete details for a single JobCrawls listing by its id, including the full description, requirements, responsibilities, benefits, salary, company, location, and a direct link to the posting. Useful after search_jobs when a user wants to know more about a specific opening; takes the id field from a search_jobs result. When the listing is sourced from Job Market Finland (Työmarkkinatori), the response has isTyomarkkinatori:true and a dataSource attribution string that MUST be shown alongside it wherever you present it, per Job Market Finland's terms of use.
| Name | Required | Description | Default |
|---|---|---|---|
| jobId | Yes | The listing id (the `id` field returned by search_jobs). Required. | |
| locale | No | Set this to the language of the user's message (fi for Finnish, sv for Swedish, en for English or any other language), even when the job titles or place names in it are English. Language to return the listing content in: en = English, fi = Finnish, sv = Swedish. Pass the same locale you searched in; this call has no query text to detect language from, so it defaults to en when omitted. If the listing is not available in that language the connector falls back to whichever language it exists in. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| url | Yes | Direct link to the individual posting on jobcrawls.com (or the source posting). |
| field | Yes | |
| title | Yes | |
| locale | Yes | Language index the listing was found in. |
| salary | Yes | Advertised salary range, or null when the listing states none. |
| skills | Yes | |
| company | Yes | |
| jobType | Yes | |
| logoUrl | Yes | |
| benefits | Yes | |
| isActive | Yes | |
| location | Yes | One location, or several for multi-location listings. |
| roleLevel | Yes | |
| brandColor | Yes | |
| companyUrl | Yes | |
| dataSource | No | Present only when isTyomarkkinatori is true. Attribution that MUST be shown alongside the listing, per Job Market Finland's terms of use. |
| postedDate | Yes | YYYY-MM-DD. |
| remoteness | Yes | |
| description | Yes | |
| marketSalary | Yes | Market salary band (gross EUR per month) for comparable jobs, only next to an employer-stated salary; null otherwise. |
| requirements | Yes | |
| employerGrade | Yes | JobCrawls Employer Score as a letter grade (A best), or null when the employer is not scored. |
| educationLevel | Yes | |
| responsibilities | Yes | |
| salaryIsEstimate | Yes | True when `salary` is a JobCrawls market-based estimate rather than stated by the employer. Say so when presenting it. |
| isTyomarkkinatori | Yes | True when the listing is sourced from Job Market Finland (Työmarkkinatori). |
| languagesRequired | Yes | |
| applicationDeadline | Yes | YYYY-MM-DD, or null when none is stated. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, so the safety profile is covered. The description still adds real behavioral context the annotations cannot: the isTyomarkkinatori:true flag, the mandatory `dataSource` attribution per Job Market Finland terms, and the locale fallback when a listing is missing in the requested language. It stops short of noting what happens for an unknown id or an unreachable source, which keeps it at 4.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with purpose, then usage, then the compliance caveat. The mid-sentence enumeration of returned fields is slightly padded, but the ordering is sensible and no sentence is redundant with the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description need not explain return values, yet it flags the one return detail with legal consequences (the required dataSource attribution) and the locale fallback behavior. Combined with the annotations, an agent has everything needed to call this correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, and the schema already documents jobId's format and locale's enum/default. The description adds cross-tool meaning by telling the agent that jobId comes from the `id` field of a search_jobs result, which is genuine value beyond the schema text.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Fetch the complete details for a single JobCrawls listing by its id') and enumerates the returned payload. It also positions itself relative to the sibling search_jobs, so an agent can distinguish this retrieval call from the search call without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names the trigger condition ('Useful after search_jobs when a user wants to know more about a specific opening') and the alternative it follows from, plus the data dependency ('takes the `id` field from a search_jobs result'). Nothing about when to reach for this tool is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_job_filtersList available job filters and valuesARead-onlyIdempotentInspect
Returns the facet attributes jobs can be filtered by (e.g. field, location, job type, seniority level, skills, and languages), together with the actual values currently present in the active listings and how many listings have each value. The values returned are the exact strings search_jobs accepts in its filters parameter for the same locale. Optionally scope the values to a query. Values come back in the language of that query when locale is omitted; pass locale explicitly to override.
| Name | Required | Description | Default |
|---|---|---|---|
| query | No | Optional free-text query to scope the facet values to a subset of listings (e.g. only the facets present in "nurse" jobs). Leave empty for the whole active index. | |
| locale | No | Set this to the language of the user's message (fi for Finnish, sv for Swedish, en for English or any other language), even when the job titles or place names in it are English. Language index whose facet values to return: en = English, fi = Finnish, sv = Swedish. When omitted, the language of "query" (detected from it) is used; pass locale explicitly to override. Values are localized: use the SAME locale you will pass to search_jobs, then feed the returned values back into search_jobs "filters" verbatim. |
Output Schema
| Name | Required | Description |
|---|---|---|
| query | Yes | |
| facets | Yes | Values to pass verbatim in search_jobs "filters" with the same locale. |
| locale | Yes | |
| booleanFilters | Yes | Boolean search_jobs parameters and what they do. |
| numericFilters | Yes | Numeric search_jobs parameters and what they do. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive with openWorldHint=false, so the safety profile is covered. The description adds real behavioral context beyond that: results are counts per value, they are localized, values reflect 'currently present' active listings, and the default language is derived from the query unless locale is passed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with the resource description, then the downstream contract, then the optional scoping/locale rules. Every sentence carries information, though the locale sentence overlaps somewhat with the schema's own locale description.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter, read-only facet-listing tool with a full output schema and complete parameter descriptions, nothing an agent needs is missing: what is returned, how counts work, how values relate to search_jobs, and how locale/query interact are all covered.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description goes beyond by linking the parameters to downstream use: query scopes values to a subset (e.g. only facets in 'nurse' jobs) and the same locale must be reused in search_jobs, reinforcing the schema's localization semantics with cross-tool intent.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific verb+resource (returns the facet attributes jobs can be filtered by) and enumerates concrete examples (field, location, job type, seniority, skills, languages). It clearly positions itself as the discovery companion to search_jobs rather than a search tool, so an agent can distinguish it from its siblings without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
States precisely when the output is useful: the returned values are 'the exact strings search_jobs accepts in its filters parameter for the same locale,' which tells the agent to call this before search_jobs and how to feed results back. It explains the query-scoping and locale-override conditions. It lacks an explicit when-not-to-use clause, but the context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_jobsSearch Finnish job listingsARead-onlyIdempotentInspect
Search active job listings on JobCrawls, an aggregator of jobs in Finland. Use for questions like "find nurse jobs in Tampere", "onko Helsingissä avoimia etätyöpaikkoja ohjelmistokehittäjälle", or "finns det lediga jobb som sjukskötare i Åbo". The index covers jobs located in Finland plus remote roles open to Finland, and has no listings for other countries (jobs in Stockholm or Berlin are out of scope). Supports free-text queries plus facet filters (field, location, job type, seniority, skills, languages, industry, education, and more). Results, filter values and job text come back in the language of the query when locale is omitted; pass locale explicitly to override. Returns a scoped, paginated list, each with title, company, location, remoteness, salary range when known, and a direct link to the individual posting. list_job_filters returns the available filter values, and get_job_details returns the full description of a result. Some results are sourced from Job Market Finland (Työmarkkinatori); those results have isTyomarkkinatori:true and a dataSource attribution string, which MUST be shown alongside that posting wherever you present it, per Job Market Finland's terms of use.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page number, starting at 1. Default: 1. | |
| sort | No | Ordering: relevance (default), date (newest first), or salary (highest minimum first). | |
| limit | No | Results per page (1–20). Default: 10. | |
| query | No | Free-text search across job title, description, skills, company, and location. Example: "senior software engineer". Leave empty to browse the newest listings. | |
| locale | No | Set this to the language of the user's message (fi for Finnish, sv for Swedish, en for English or any other language), even when the job titles or place names in it are English. Language index to search: en = English, fi = Finnish, sv = Swedish. When omitted, results, filter values and job text come back in the language of "query" (detected from it); pass locale explicitly to override. Listing content AND filter values are localized per language, so keep this consistent with the locale used for list_job_filters. Prefer "fi" for the broadest coverage of jobs in Finland. | |
| filters | No | Facet filters keyed by attribute, each an array of allowed values (values within one attribute are OR-combined; different attributes are AND-combined). Allowed keys: field, normalisedTitle, normalisedRoleLevel, location, companyIndustry, companyId, jobType, requiredLanguages, optionalLanguages, benefits, skillsAndTechnologies, educationLevel, peopleManagementTier, remoteness, regionTags. Values are case-sensitive, LANGUAGE-SPECIFIC, and must match the chosen locale index — call list_job_filters with the same locale first to discover the exact values (e.g. field is "Software Engineering" in en but its Finnish equivalent in fi). Example (en): { "field": ["Software Engineering"], "location": ["Helsinki, Finland"] }. regionTags takes the `placeId` of an entry in a previous result's `regions` (a Finnish region). | |
| minSalary | No | Only listings whose minimum salary is at least this amount (listing currency, usually EUR). | |
| remoteOnly | No | Shortcut for only fully remote positions (remoteness = Remote). | |
| includeFacets | No | When true, also return the facet values and counts for the current result set, plus `regions` (job counts per Finnish region), so you can refine the search. Default: false. | |
| excludeFilters | No | Negative facet filters keyed by attribute, same shape as `filters` but EXCLUDES listings matching any of the given values instead of requiring them. Use this to ask for jobs that do NOT have a given attribute value. Allowed keys: field, normalisedTitle, normalisedRoleLevel, location, companyIndustry, companyId, jobType, requiredLanguages, optionalLanguages, benefits, skillsAndTechnologies, educationLevel, peopleManagementTier, remoteness, regionTags. Same locale rules as `filters` apply. Example (en): { "requiredLanguages": ["Finnish"] } returns jobs that do not require Finnish. A key present in both `filters` and `excludeFilters` is invalid. |
Output Schema
| Name | Required | Description |
|---|---|---|
| page | Yes | |
| query | Yes | The free-text query used, or null when browsing without one. |
| facets | No | Present only when includeFacets was true. |
| locale | Yes | Language index that was searched. |
| hasMore | Yes | True when a further page exists. |
| regions | No | Present only when includeFacets was true: job counts per Finnish region (maakunta), largest first. Pass `placeId` in filters.regionTags to narrow to one region. |
| results | Yes | |
| pageSize | Yes | |
| returned | Yes | Number of results in this page. |
| totalFound | Yes | Total matching active listings. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive, closed-world), yet the description adds non-obvious behavioral obligations: the mandatory dataSource attribution for Työmarkkinatori results, the isTyomarkkinatori flag, locale-driven result language, and paginated scoping. This is exactly the value-add expected when structured fields already carry the basics.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core purpose and scope, then layers filters, locale, return shape, and attribution in a logical order. Dense but each sentence carries information; the locale explanation is somewhat redundant with the schema and could be tightened.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 10-parameter, nested-filter, output-schema-backed search tool, everything an agent needs is present: scope, examples, filter mechanics, locale semantics, sibling routing, and legal attribution requirements. Return values are covered by the output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description goes beyond it by explaining cross-parameter/cross-tool coordination: facet values must match the selected locale index and be discovered via list_job_filters with the same locale, and locale must track the user's message language. It adds little on pagination/sort, which the schema already covers.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Search active job listings on JobCrawls, an aggregator of jobs in Finland') and pins the geographic scope precisely, explicitly excluding Stockholm/Berlin. An agent can distinguish it from list_job_filters and get_job_details without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete trigger examples in three languages, states the scope boundary (Finland-located plus remote-open-to-Finland, nothing else), and routes to siblings: list_job_filters for filter values and get_job_details for full descriptions. Both when-to-use and when-not-to-use are covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
4 tool updates
- First observed
calculate_net_salary_finland - First observed
get_job_details - First observed
list_job_filters - First observed
search_jobs
Related MCP Connectors
Read-only European tax, salary and benefit calculators with official sources and unknowns.
Search live job openings in many countries and languages, and read a full job ad.
Job listings in Portugal: search, salary statistics, comparables and companies.
Read-only payroll calculations and multi-country tax comparisons for eight countries.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceSearch Statistics Finland's StatFin database (3,000+ tables), inspect table variables, and query clean flattened statistics on population, economy, labour and regions.10 npmMIT
- AlicenseNot gradedqualityDmaintenanceProvides access to the Finnish company registry (PRH/YTJ) to search for businesses and retrieve detailed information using Business IDs. It enables users to perform industry-specific searches and track recent company registrations through official government open data.14 npmMIT
- FlicenseNot gradedqualityDmaintenanceEnables querying real disclosed salary data across 20 regions, with tools to search jobs, retrieve salary statistics, and find similar roles.-
- AlicenseNot gradedqualityDmaintenanceVerified job search: every listing is opened and confirmed live and accepting applicants within the last 72 hours, and re-verified on a rolling clock, so agents can recommend jobs without ghost-job or dead-link risk. Read-only, no auth.MIT
Glama MCP Gateway
Add one secure layer between your agents and this server.