@sfranalytics/mcp 0.6.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -63,7 +63,6 @@ Notes:
63
63
  - `MCP_STRICT_TOKEN_VALIDATION=true` optionally validates token(s) on each MCP request via upstream auth probes.
64
64
  - In strict mode, explicit auth failures return `401`; temporary probe outages return `503`.
65
65
  - Raw HTTP clients should send `Accept: application/json, text/event-stream`.
66
- - HTTP mode currently excludes Snowflake tools.
67
66
 
68
67
  ## API Keys
69
68
 
@@ -72,7 +71,7 @@ You can configure one or both API keys. Tools are enabled based on which keys yo
72
71
  | Key | Enables | Tools |
73
72
  |-----|---------|-------|
74
73
  | `SFR_API_TOKEN` | Property data, buyer intelligence, market analytics | 21 tools |
75
- | `PLR_API_TOKEN` | Private lending, borrower/lender intelligence | 15 tools |
74
+ | `PLR_API_TOKEN` | Private lending, borrower/lender intelligence | 17 tools |
76
75
 
77
76
  Get your API keys at [sfranalytics.com](https://www.sfranalytics.com).
78
77
 
@@ -88,13 +87,14 @@ Get your API keys at [sfranalytics.com](https://www.sfranalytics.com).
88
87
  | Buyer Intelligence | 5 | Top buyers, investor profiles, growth trends, best deals, market highlights |
89
88
  | Market Activity | 4 | Investor transactions, flip stats, flip activity, activity snapshots |
90
89
 
91
- ### PLR API (15 tools)
90
+ ### PLR API (17 tools)
92
91
 
93
92
  | Category | Tools | Description |
94
93
  |----------|-------|-------------|
95
94
  | Borrower Intelligence | 6 | Search, profiles, rankings, top borrowers, loan history, contacts |
96
95
  | Lender Intelligence | 4 | Rankings, top lenders, lender clients, churned borrowers |
97
96
  | Market & Portfolio | 5 | Nationwide trends, MSA rankings, nearby loans, transaction feed, portfolio totals |
97
+ | Risk & Owner Intelligence | 2 | Negative remarks and principal/owner search |
98
98
 
99
99
  ### Shared
100
100
 
package/dist/config.js CHANGED
@@ -5,6 +5,12 @@ function env(name) {
5
5
  const v = process.env[name];
6
6
  return v && v.trim() ? v.trim() : undefined;
7
7
  }
8
+ function parseBoolean(input) {
9
+ if (!input)
10
+ return false;
11
+ const normalized = input.trim().toLowerCase();
12
+ return normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on";
13
+ }
8
14
  /** Optional local secrets file for dev convenience. Keep it out of git. */
9
15
  function loadLocalSecrets() {
10
16
  const filename = env("MCP_LOCAL_SECRETS") ??
@@ -28,19 +34,11 @@ export function loadConfig() {
28
34
  const sfAccount = get("SNOWFLAKE_ACCOUNT");
29
35
  const sfUser = get("SNOWFLAKE_USERNAME");
30
36
  const sfPass = get("SNOWFLAKE_PASSWORD");
31
- if (!sfrToken && !plrToken && !sfAccount) {
32
- throw new Error([
33
- "No API tokens configured. Set at least one:",
34
- "",
35
- " SFR_API_TOKEN — property data, buyer intelligence, market analytics (21 tools)",
36
- " PLR_API_TOKEN — private lending, borrower/lender intelligence (15 tools)",
37
- " SNOWFLAKE_ACCOUNT — Redfin market data, census, rental yield, investor activity (10 tools)",
38
- "",
39
- "Get your API keys at https://www.sfranalytics.com",
40
- "Questions? support@sfranalytics.com",
41
- ].join("\n"));
37
+ const enableInternalSnowflake = parseBoolean(get("MCP_ENABLE_INTERNAL_SNOWFLAKE"));
38
+ if (!enableInternalSnowflake && (sfAccount || sfUser || sfPass)) {
39
+ console.error("Snowflake credentials detected but ignored. Set MCP_ENABLE_INTERNAL_SNOWFLAKE=true to enable internal-only Snowflake tools.");
42
40
  }
43
- const snowflake = sfAccount && sfUser && sfPass
41
+ const snowflake = enableInternalSnowflake && sfAccount && sfUser && sfPass
44
42
  ? {
45
43
  account: sfAccount,
46
44
  username: sfUser,
@@ -50,6 +48,19 @@ export function loadConfig() {
50
48
  warehouse: get("SNOWFLAKE_WAREHOUSE") ?? "COMPUTE_WH",
51
49
  }
52
50
  : null;
51
+ if (!sfrToken && !plrToken && !snowflake) {
52
+ const lines = [
53
+ "No API tokens configured. Set at least one:",
54
+ "",
55
+ " SFR_API_TOKEN — property data, buyer intelligence, market analytics (21 tools)",
56
+ " PLR_API_TOKEN — private lending, borrower/lender intelligence (17 tools)",
57
+ ];
58
+ if (enableInternalSnowflake) {
59
+ lines.push(" SNOWFLAKE_ACCOUNT + SNOWFLAKE_USERNAME + SNOWFLAKE_PASSWORD", " — internal-only staging tools");
60
+ }
61
+ lines.push("", "Get your API keys at https://www.sfranalytics.com", "Questions? support@sfranalytics.com");
62
+ throw new Error(lines.join("\n"));
63
+ }
53
64
  return {
54
65
  sfr: sfrToken
55
66
  ? {
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import { disconnectSnowflake, isSnowflakeConfigured } from "./services/snowflake
7
7
  async function main() {
8
8
  const config = loadConfig();
9
9
  const sfrCount = config.sfr ? 21 : 0;
10
- const plrCount = config.plr ? 15 : 0;
10
+ const plrCount = config.plr ? 17 : 0;
11
11
  const sfCount = config.snowflake ? 10 : 0;
12
12
  const parts = [];
13
13
  if (config.sfr)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sfranalytics/mcp",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "MCP server for SFR Analytics — single-family rental property data, buyer intelligence, and private lending insights",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -12,8 +12,7 @@
12
12
  "homepage": "https://www.sfranalytics.com",
13
13
  "main": "dist/index.js",
14
14
  "bin": {
15
- "sfranalytics-mcp": "dist/index.js",
16
- "sfranalytics-mcp-http": "dist/http.js"
15
+ "sfranalytics-mcp": "dist/index.js"
17
16
  },
18
17
  "files": [
19
18
  "dist",