-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathconfig.js
More file actions
160 lines (124 loc) · 6.47 KB
/
Copy pathconfig.js
File metadata and controls
160 lines (124 loc) · 6.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
// ============================================================================
// MCP SERVER CONFIGURATION
// ============================================================================
//
// Runtime configuration for the Lebanon zoning MCP server.
//
// ============================================================================
// ----------------------------------------------------------------------------
// SERVER IDENTITY
// ----------------------------------------------------------------------------
export const SERVER_NAME = "lebanon-zoning-lookup";
export const SERVER_VERSION = "4.0.0";
// ----------------------------------------------------------------------------
// DATA SOURCE CONFIGURATION
// ----------------------------------------------------------------------------
export const NODE_ENV = process.env.NODE_ENV || 'development';
export const BASE_URL = process.env.ARCGIS_BASE_URL;
if (!BASE_URL) {
console.error("ERROR: ARCGIS_BASE_URL secret is required but not set.");
console.error("Please add this secret in Replit's Secrets tab.");
process.exit(1);
}
export const ZONING_LAYER = process.env.ZONING_LAYER || "24";
export const ADDRESS_LAYER_NAME = process.env.ADDRESS_LAYER_NAME || "LebanonNHMATMassGeoExport_Layer";
// ----------------------------------------------------------------------------
// LOCATION-SPECIFIC STRINGS
// ----------------------------------------------------------------------------
export const LOCATION_NAME = "Lebanon, NH";
export const DATA_SOURCES = {
zoningLayer: "Lebanon Official Zoning Layer",
addressTable: "Lebanon Master Address Table",
};
// ----------------------------------------------------------------------------
// TOOL DESCRIPTIONS
// ----------------------------------------------------------------------------
export const TOOL_DESCRIPTIONS = {
lookupByCoordinates:
`Look up the zoning district for a location in ${LOCATION_NAME} using latitude and longitude coordinates. Returns the official zoning district from the ${DATA_SOURCES.zoningLayer}.`,
lookupByAddress:
`Look up the zoning district for a location in ${LOCATION_NAME} using a street address. Searches the ${DATA_SOURCES.addressTable} and returns the zoning district along with the full address and coordinates. Returns multiple matches if the address is ambiguous.`,
};
// ----------------------------------------------------------------------------
// ERROR EXAMPLES
// ----------------------------------------------------------------------------
export const ERROR_EXAMPLES = {
coordinates: { lat: 43.6426, lon: -72.2515 },
address: "123 Main Street"
};
// ----------------------------------------------------------------------------
// PAYLOAD LIMITS
// ----------------------------------------------------------------------------
export const PAYLOAD_LIMITS = {
httpBodySize: '32kb',
fields: {
address: 500,
layerId: 10,
districtName: 100,
genericString: 1000,
},
coordinates: {
latMin: -90,
latMax: 90,
lonMin: -180,
lonMax: 180,
},
};
// ----------------------------------------------------------------------------
// SERVER PORT
// ----------------------------------------------------------------------------
export const PORT = process.env.PORT || 5000;
// ----------------------------------------------------------------------------
// AUTHENTICATION (STEP 4)
// ----------------------------------------------------------------------------
// Auth is ON by default; set REQUIRE_AUTH=false to explicitly disable it.
export const REQUIRE_AUTH = process.env.REQUIRE_AUTH !== 'false';
export const MCP_BEARER_TOKEN = process.env.MCP_BEARER_TOKEN || '';
if (REQUIRE_AUTH && !MCP_BEARER_TOKEN) {
console.error("ERROR: MCP_BEARER_TOKEN is required when REQUIRE_AUTH is enabled.");
console.error("Set MCP_BEARER_TOKEN or explicitly set REQUIRE_AUTH=false for local unauthenticated use.");
process.exit(1);
}
// ----------------------------------------------------------------------------
// STATELESS MODE (STEP 6 OVERRIDE)
// ----------------------------------------------------------------------------
export const ALLOW_STATELESS = process.env.ALLOW_STATELESS === undefined
? NODE_ENV !== 'production'
: process.env.ALLOW_STATELESS !== 'false';
// ----------------------------------------------------------------------------
// SESSION LIFECYCLE
// ----------------------------------------------------------------------------
// Maximum number of concurrent server-side sessions.
export const MAX_SESSIONS = parseInt(process.env.MAX_SESSIONS || '100', 10);
// Milliseconds of inactivity before a session is reaped (default: 30 minutes).
export const SESSION_TIMEOUT_MS = parseInt(process.env.SESSION_TIMEOUT_MS || '1800000', 10);
// How often the reaper runs (default: 5 minutes).
export const SESSION_REAPER_INTERVAL_MS = parseInt(process.env.SESSION_REAPER_INTERVAL_MS || '300000', 10);
// ----------------------------------------------------------------------------
// RATE LIMITING (STEP 5)
// ----------------------------------------------------------------------------
export const RATE_LIMIT_WINDOW_MS = parseInt(process.env.RATE_LIMIT_WINDOW_MS || '60000', 10);
export const RATE_LIMIT_MAX_REQUESTS = parseInt(process.env.RATE_LIMIT_MAX_REQUESTS || '60', 10);
export const RATE_LIMIT_AUTH_MULTIPLIER = parseFloat(process.env.RATE_LIMIT_AUTH_MULTIPLIER || '2');
// ----------------------------------------------------------------------------
// CACHING (STEP 5)
// ----------------------------------------------------------------------------
export const CACHE_TTL_SECONDS = parseInt(process.env.CACHE_TTL_SECONDS || '300', 10);
export const CACHE_MAX_ENTRIES = parseInt(process.env.CACHE_MAX_ENTRIES || '500', 10);
// ----------------------------------------------------------------------------
// RESPONSE LIMITS (STEP 7)
// ----------------------------------------------------------------------------
export const MAX_FIELDS = parseInt(process.env.MAX_FIELDS || '40', 10);
// ----------------------------------------------------------------------------
// CORS (STEP 8)
// ----------------------------------------------------------------------------
const corsOriginsEnv = process.env.CORS_ALLOW_ORIGINS || '';
export const CORS_ALLOW_ORIGINS = corsOriginsEnv
.split(',')
.map(o => o.trim())
.filter(o => o.length > 0);
if (NODE_ENV === 'production' && CORS_ALLOW_ORIGINS.length === 0) {
console.error("ERROR: CORS_ALLOW_ORIGINS must be set in production.");
console.error("Use a comma-separated list of trusted origins.");
process.exit(1);
}